@tequila99/githuman 0.5.0 → 0.7.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 +24 -2
- package/dist/server/errors/git.js +2 -0
- package/dist/server/routes/agent.js +8 -2
- package/dist/server/routes/git.js +5 -2
- package/dist/server/services/agent/agent-session.js +2 -1
- package/dist/server/services/agent/context-builder.js +49 -2
- package/dist/server/services/agent/file-index.js +7 -4
- package/dist/server/services/git.service.js +44 -4
- package/dist/server/utils/sse.js +76 -5
- package/dist/shared/agents/file-search.js +19 -7
- package/dist/shared/agents/mention-paths.js +40 -0
- package/dist/shared/agents/schemas.js +13 -4
- package/dist/shared/git/schemas.js +4 -1
- package/dist/shared/utils/guards.js +3 -0
- package/dist/web/assets/{AppPage-D_OHhrKS.js → AppPage-BGcEFW_o.js} +2 -2
- package/dist/web/assets/CreateReviewFabButton-CdUXVriU.js +1 -0
- package/dist/web/assets/{ErrorNotFound-jc5_L_-4.js → ErrorNotFound-CYOZg8yN.js} +1 -1
- package/dist/web/assets/IndexPage-CYFIGWy9.css +1 -0
- package/dist/web/assets/IndexPage-OqgW0yH8.js +1 -0
- package/dist/web/assets/MainLayout-Bi0JE3ER.js +11 -0
- package/dist/web/assets/MainLayout-DPkSlqMr.css +1 -0
- package/dist/web/assets/PdfPreview-CIiKnzQN.js +54 -0
- package/dist/web/assets/PdfPreview-Cb0xawi0.css +1 -0
- package/dist/web/assets/{QBtn-Bgm40omM.js → QBtn-CzrOO1zA.js} +1 -1
- package/dist/web/assets/{QBadge-BY-jTQ8w.js → QScrollArea-C4BKutrt.js} +1 -1
- package/dist/web/assets/QSelect-BXUaq4ky.js +1 -0
- package/dist/web/assets/QSpace-BMpRu3a-.js +13 -0
- package/dist/web/assets/ReviewDetailPage-CkCilMNW.css +1 -0
- package/dist/web/assets/ReviewDetailPage-DlR7Vxkw.js +1 -0
- package/dist/web/assets/ReviewsPage-DM8XtlUK.js +1 -0
- package/dist/web/assets/StatusSwitcher-Blg5JmAa.js +1 -0
- package/dist/web/assets/StatusSwitcher-DTD5inU1.css +1 -0
- package/dist/web/assets/{TerminalView-B11UHZv3.css → TerminalView-BurzSD2L.css} +1 -1
- package/dist/web/assets/TerminalView-Ch-ndYr6.js +19 -0
- package/dist/web/assets/{abnfDiagram-O67JEVCF-4qpB0CGh.js → abnfDiagram-O67JEVCF-Cab71FlB.js} +1 -1
- package/dist/web/assets/agent-store-CDuiBhST.js +1 -0
- package/dist/web/assets/app-info-store-BmD_P8q2.js +1 -0
- package/dist/web/assets/architecture-7GRP2DOG-DMgDJZyQ.js +1 -0
- package/dist/web/assets/{architectureDiagram-NJMV4G6O-CEL-_i5O.js → architectureDiagram-NJMV4G6O-Dl1WKOEi.js} +1 -1
- package/dist/web/assets/{blockDiagram-BEXU5L5S-bMrUf1GU.js → blockDiagram-BEXU5L5S-CZ3Lxybj.js} +1 -1
- package/dist/web/assets/{c4Diagram-YGBWAQC7-C54mp6dl.js → c4Diagram-YGBWAQC7-ULi06PEd.js} +1 -1
- package/dist/web/assets/channel-BnUyOMnk.js +1 -0
- package/dist/web/assets/{chunk-3FUC2YCW-BtIughAT.js → chunk-3FUC2YCW-B1f60wx3.js} +1 -1
- package/dist/web/assets/{chunk-5DYCD2WN-BhyMEDuJ.js → chunk-5DYCD2WN-f6Pcl3dF.js} +1 -1
- package/dist/web/assets/{chunk-742MDFTN-8MczzxE2.js → chunk-742MDFTN-szX1QirW.js} +1 -1
- package/dist/web/assets/{chunk-7INBJB4K-BdS9oIIG.js → chunk-7INBJB4K-CP_ynmAQ.js} +1 -1
- package/dist/web/assets/{chunk-7M6MHVWA-BU5_UwaZ.js → chunk-7M6MHVWA-DPL74uZE.js} +5 -5
- package/dist/web/assets/{chunk-7PRAP22T-BaAw-gEj.js → chunk-7PRAP22T-DH9TawZY.js} +1 -1
- package/dist/web/assets/{chunk-GTNCS2PH-DNpH8E_x.js → chunk-GTNCS2PH-CKAuGvnf.js} +1 -1
- package/dist/web/assets/{chunk-GWA4HPMP-BvG5tXy2.js → chunk-GWA4HPMP-DTbHCHSN.js} +1 -1
- package/dist/web/assets/{chunk-MBY4JIJT-B8XJMHG2.js → chunk-MBY4JIJT-ClgvJMtC.js} +1 -1
- package/dist/web/assets/{chunk-NETBCI7D-ClCXW1dx.js → chunk-NETBCI7D-Dq5Z7z8S.js} +1 -1
- package/dist/web/assets/{chunk-O7XYJQB3-BNcB0oiZ.js → chunk-O7XYJQB3-C0By5mcm.js} +1 -1
- package/dist/web/assets/{chunk-UA2S7LBM-CS5CtIsj.js → chunk-UA2S7LBM-BtquYpxe.js} +1 -1
- package/dist/web/assets/{chunk-WEXAMYUT-CJaZJWKF.js → chunk-WEXAMYUT-BlZL42XJ.js} +1 -1
- package/dist/web/assets/{chunk-Z7XXMR3K-DP2k1Ci5.js → chunk-Z7XXMR3K-BbtQbAvv.js} +1 -1
- package/dist/web/assets/{chunk-ZIGJFQKS-y4KHfdEv.js → chunk-ZIGJFQKS-tC_YdRrm.js} +1 -1
- package/dist/web/assets/{classDiagram-v2-NBCMYWYE-C-kWcloV.js → classDiagram-v2-NBCMYWYE-CvlA_A4N.js} +4 -4
- package/dist/web/assets/create-BSmXD9Zr.js +1 -0
- package/dist/web/assets/{cynefin-OW5HDTMX-C3AwH_vU.js → cynefin-OW5HDTMX-DFbhKkIi.js} +1 -1
- package/dist/web/assets/{cynefinDiagram-VND7K2PF-DYF_CoB8.js → cynefinDiagram-VND7K2PF-DHGaLNQN.js} +1 -1
- package/dist/web/assets/{dagre-6A5THRUB-DWCEmsd1.js → dagre-6A5THRUB-Bk3Po5o5.js} +1 -1
- package/dist/web/assets/{diagram-22UHCM2B-oBFhSpao.js → diagram-22UHCM2B-Djjo5ftL.js} +8 -8
- package/dist/web/assets/{diagram-3UASUU5V-Cj9rB07y.js → diagram-3UASUU5V-BcP7pJru.js} +1 -1
- package/dist/web/assets/{diagram-ATOU4E4O-D4H9BqUQ.js → diagram-ATOU4E4O-o_vsc8em.js} +1 -1
- package/dist/web/assets/{diagram-CDSNMT55-qLgJBiIs.js → diagram-CDSNMT55-eyN9Aru8.js} +1 -1
- package/dist/web/assets/{diagram-MLGK6HIB-Bhhvtx0A.js → diagram-MLGK6HIB-Dfjipnvb.js} +1 -1
- package/dist/web/assets/{diagram-MPIPVDR6-O4wokd54.js → diagram-MPIPVDR6-C2chocRe.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-ZINNZB2B-BRU7SszO.js → ebnfDiagram-ZINNZB2B-CE58dwC-.js} +1 -1
- package/dist/web/assets/{elk-276RUBZZ-r0X8f7Sv.js → elk-276RUBZZ-KyTn9aJi.js} +1 -1
- package/dist/web/assets/{erDiagram-OPXOYQCR-DbgjsGkX.js → erDiagram-OPXOYQCR-D9aOi7ZD.js} +1 -1
- package/dist/web/assets/eventmodeling-NTZA5JFV-7YdTAmVS.js +1 -0
- package/dist/web/assets/flowDiagram-KWPJA3E3-eOIiY2oF.js +1 -0
- package/dist/web/assets/{ganttDiagram-FUAMR5RP-BwhUglGo.js → ganttDiagram-FUAMR5RP-DRAI6xWM.js} +1 -1
- package/dist/web/assets/{gitGraph-4MIJSDKK-DA11BsSo.js → gitGraph-4MIJSDKK-D1lAB6tr.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-X574FWY7-BdG7d-11.js → gitGraphDiagram-X574FWY7-77GVnwya.js} +1 -1
- package/dist/web/assets/i18n-C5Xnmkwe.js +1 -0
- package/dist/web/assets/index-BqedItFI.js +2 -0
- package/dist/web/assets/{index-BatRsx0U.css → index-Dma-RXBR.css} +1 -1
- package/dist/web/assets/{info-A6RAGUB7-BxzfvGqu.js → info-A6RAGUB7-Di1qRpwO.js} +1 -1
- package/dist/web/assets/{infoDiagram-VRGFBTTK-veq817ut.js → infoDiagram-VRGFBTTK-gceHneJ0.js} +1 -1
- package/dist/web/assets/init-app-IHgDyoRH.js +1 -0
- package/dist/web/assets/{is-EbmiuVzv.js → is-DssfAlMe.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-DMuzkArR.js → ishikawaDiagram-OU5B5YK6-B9QDQoSG.js} +1 -1
- package/dist/web/assets/{journeyDiagram-ZHPQQLJL-Cqj0kbKe.js → journeyDiagram-ZHPQQLJL-CVTMW0pg.js} +1 -1
- package/dist/web/assets/{kanban-definition-PNTS6WVX-DUvral0v.js → kanban-definition-PNTS6WVX-TNoWYrUr.js} +1 -1
- package/dist/web/assets/{line-DcLaUOyJ.js → line-B_1CHIjZ.js} +1 -1
- package/dist/web/assets/{mermaid-parser.core-CY7nVQ2O.js → mermaid-parser.core-LAeoGxkL.js} +3 -3
- package/dist/web/assets/{mermaid.core-Cz083qmW.js → mermaid.core-DMppSzfM.js} +7 -7
- package/dist/web/assets/{mindmap-definition-NLK3R4M7--Twjhxcv.js → mindmap-definition-NLK3R4M7-DJ-6nTWg.js} +1 -1
- package/dist/web/assets/{packet-AYTQ26CC-Csf3Pf50.js → packet-AYTQ26CC-B4tvN4nf.js} +1 -1
- package/dist/web/assets/pdf.worker-C2cQdohj.js +48 -0
- package/dist/web/assets/{pegDiagram-GJSIUBJH-vVjFUYc4.js → pegDiagram-GJSIUBJH-BwQ6jaVw.js} +1 -1
- package/dist/web/assets/{pie-WAS4IAKB-CyUE71ZQ.js → pie-WAS4IAKB-ZwlyCxls.js} +1 -1
- package/dist/web/assets/{pieDiagram-5QR66LMP-CV24sdEs.js → pieDiagram-5QR66LMP-BDYLBnB1.js} +1 -1
- package/dist/web/assets/pinia-BKoxNmoW.js +1 -0
- package/dist/web/assets/{pinia-ri8AYppz.js → pinia-DCsnCHsH.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-O4NWA36T-GVAUaTqf.js → quadrantDiagram-O4NWA36T-CkmLCxOG.js} +1 -1
- package/dist/web/assets/{radar-RG4KPBEZ-D7YGMFYX.js → radar-RG4KPBEZ-Ca7H5QOY.js} +1 -1
- package/dist/web/assets/{railroad-74A4TZTK-BYsDf4cg.js → railroad-74A4TZTK-CX3Z2QYJ.js} +1 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-DZSn8MK2.js +1 -0
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-BVTJtDBq.js +1 -0
- package/dist/web/assets/railroad-peg-WCYAUIDC-DMzsNGzj.js +1 -0
- package/dist/web/assets/{railroadDiagram-XR7U4H2S-DOyP7Y6B.js → railroadDiagram-XR7U4H2S-D8ii6sM4.js} +1 -1
- package/dist/web/assets/{requirementDiagram-PLB6GJNP-C2CJ05_O.js → requirementDiagram-PLB6GJNP-iHY-tE7c.js} +1 -1
- package/dist/web/assets/{runtime-core.esm-bundler-CF89Lyp2.js → runtime-core.esm-bundler-BKFI1w28.js} +1 -1
- package/dist/web/assets/{safe-storage-BpHrcFXl.js → safe-storage-BCP757jk.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-IPEJSGJF-rYUTxo-7.js → sankeyDiagram-IPEJSGJF-CBprSUZk.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-PO4LG4MO-Dy-NGv9K.js → sequenceDiagram-PO4LG4MO-BkphpOQ_.js} +1 -1
- package/dist/web/assets/{stateDiagram-v2-GCMORJYK-_uEXf3B4.js → stateDiagram-v2-GCMORJYK-HN1RwAPZ.js} +2 -2
- package/dist/web/assets/{swimlanes-2SLR337P-CcejXyI9.js → swimlanes-2SLR337P-Cc8jyETz.js} +1 -1
- package/dist/web/assets/swimlanesDiagram-TC7HE7FX-BxXXHQ70.js +8 -0
- package/dist/web/assets/theme-CPoPdFci.js +1 -0
- package/dist/web/assets/{timeline-definition-EJHVYXUP-CSry3jW1.js → timeline-definition-EJHVYXUP-Bas0Ksw6.js} +1 -1
- package/dist/web/assets/{treeView-Q6P3EWNA-CUCgNMVi.js → treeView-Q6P3EWNA-Ck-xt3KO.js} +1 -1
- package/dist/web/assets/{treemap-WGGIJYW6-BtG_xZt4.js → treemap-WGGIJYW6-k9Ay9d-c.js} +1 -1
- package/dist/web/assets/use-app-theme-BfRqhHi_.js +1 -0
- package/dist/web/assets/use-panel-width-C9dWftsJ.js +1 -0
- package/dist/web/assets/use-server-events-znzHKZZx.js +1 -0
- package/dist/web/assets/{use-virtual-scroll-DTEGubei.js → use-virtual-scroll-CIwaJCUj.js} +1 -1
- package/dist/web/assets/{usecaseDiagram-POWQR4AR-BY2X6VR2.js → usecaseDiagram-POWQR4AR-BlzYgvXB.js} +1 -1
- package/dist/web/assets/{vennDiagram-UO4OBE2U-D-khbRsr.js → vennDiagram-UO4OBE2U-gjloIQdf.js} +1 -1
- package/dist/web/assets/{vue-i18n.runtime-BTqPc4vG.js → vue-i18n.runtime-BpRrzZrT.js} +2 -2
- package/dist/web/assets/{wardley-WFR3VGLG-BwwTtxgX.js → wardley-WFR3VGLG-BnsYd7B2.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-VNRHLVJA-N4eN_Mx8.js → wardleyDiagram-VNRHLVJA-ktflnFLZ.js} +1 -1
- package/dist/web/assets/{xychartDiagram-PMCCYNJV-Bp3do5lv.js → xychartDiagram-PMCCYNJV-Ch5MYgz0.js} +1 -1
- package/dist/web/index.html +6 -6
- package/dist/web/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/dist/web/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/dist/web/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/dist/web/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/LICENSE +36 -0
- package/dist/web/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/Roman.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/V.bcmap +0 -0
- package/dist/web/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/dist/web/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/dist/web/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
- package/dist/web/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/dist/web/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/dist/web/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/dist/web/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/dist/web/pdfjs/wasm/LICENSE_JBIG2 +196 -0
- package/dist/web/pdfjs/wasm/LICENSE_OPENJPEG +39 -0
- package/dist/web/pdfjs/wasm/LICENSE_PDFJS_JBIG2 +13 -0
- package/dist/web/pdfjs/wasm/LICENSE_PDFJS_OPENJPEG +22 -0
- package/dist/web/pdfjs/wasm/LICENSE_PDFJS_QCMS +19 -0
- package/dist/web/pdfjs/wasm/LICENSE_QCMS +21 -0
- package/dist/web/pdfjs/wasm/jbig2.wasm +0 -0
- package/dist/web/pdfjs/wasm/jbig2_nowasm_fallback.js +15 -0
- package/dist/web/pdfjs/wasm/openjpeg.wasm +0 -0
- package/dist/web/pdfjs/wasm/openjpeg_nowasm_fallback.js +17 -0
- package/dist/web/pdfjs/wasm/qcms_bg.wasm +0 -0
- package/dist/web/pdfjs/wasm/quickjs-eval.js +16 -0
- package/dist/web/pdfjs/wasm/quickjs-eval.wasm +0 -0
- package/package.json +3 -1
- package/dist/web/assets/CreateReviewFabButton-B737aIvn.js +0 -1
- package/dist/web/assets/IndexPage-DzlFTw_b.js +0 -1
- package/dist/web/assets/IndexPage-u_qqIPRL.css +0 -1
- package/dist/web/assets/MainLayout-DaSyo22r.js +0 -8
- package/dist/web/assets/MainLayout-DoniW026.css +0 -1
- package/dist/web/assets/QSelect-713AWDd_.js +0 -1
- package/dist/web/assets/QSpace-BLu5AyZv.css +0 -1
- package/dist/web/assets/QSpace-BVBU-0oC.js +0 -17
- package/dist/web/assets/ReviewDetailPage-CLM6aU4u.js +0 -1
- package/dist/web/assets/ReviewDetailPage-CP6YqXPT.css +0 -1
- package/dist/web/assets/ReviewsPage-bllnaoOS.js +0 -1
- package/dist/web/assets/StatusSwitcher-BZ4FYVnY.js +0 -2
- package/dist/web/assets/StatusSwitcher-BxRuEHHQ.css +0 -1
- package/dist/web/assets/TerminalView-Ci9CNTyY.js +0 -19
- package/dist/web/assets/agent-store-DIma0R4U.js +0 -1
- package/dist/web/assets/app-info-store-BzsJOxVc.js +0 -1
- package/dist/web/assets/architecture-7GRP2DOG-DG6nf_hE.js +0 -1
- package/dist/web/assets/channel-CS4rbjhf.js +0 -1
- package/dist/web/assets/create-CSUVwdx4.js +0 -1
- package/dist/web/assets/eventmodeling-NTZA5JFV-1Q8-FsiO.js +0 -1
- package/dist/web/assets/export-file-Di_2jvjP.js +0 -1
- package/dist/web/assets/flowDiagram-KWPJA3E3-BbwsRPsv.js +0 -1
- package/dist/web/assets/i18n-D1K2AGeW.js +0 -1
- package/dist/web/assets/index-DuCIKkvf.js +0 -2
- package/dist/web/assets/init-app-DKRVN8HV.js +0 -1
- package/dist/web/assets/pinia-UjhgYLzw.js +0 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-Bg7f5Sbu.js +0 -1
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-ufUodNib.js +0 -1
- package/dist/web/assets/railroad-peg-WCYAUIDC-YvUtEf_g.js +0 -1
- package/dist/web/assets/swimlanesDiagram-TC7HE7FX-I9_cJ2VX.js +0 -8
- package/dist/web/assets/theme-Dv0yhgRD.js +0 -1
- package/dist/web/assets/use-app-theme-CSRcIN0e.js +0 -1
- package/dist/web/assets/use-panel-width-DNg6NE2M.js +0 -1
- package/dist/web/assets/use-server-events-CYiRauy1.js +0 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ staged/unstaged diff, сравнение веток и коммитов, бра
|
|
|
20
20
|
файлов в репозитории — удобно смотреть, как редактирует код AI-агент.
|
|
21
21
|
После перезапуска `serve` уже открытые вкладки перезагружаются сами.
|
|
22
22
|
- Чаты с ACP-агентами (Claude Code, Cursor, Codex, pi): до 5 чатов во
|
|
23
|
-
вкладках, контекст — diff, файл целиком, ревью, вложения и `@`-файлы из
|
|
23
|
+
вкладках, контекст — diff, файл целиком, ревью, вложения и `@`-файлы и папки из
|
|
24
24
|
репозитория. Подробнее — в разделе «Агенты» ниже.
|
|
25
25
|
- Ручной/авто выбор тёмной-светлой темы.
|
|
26
26
|
- CLI: `serve` (поднять сервер), `list`/`export` (быстрый доступ к
|
|
@@ -77,7 +77,13 @@ node dist/cli/index.js export last --format markdown -o review.md
|
|
|
77
77
|
репозитория; нужные адаптеры подтягиваются через `npx` при первом запуске.
|
|
78
78
|
|
|
79
79
|
- **Контекст.** «Add to chat» в меню файла и diff, кнопка у активного
|
|
80
|
-
ревью; в поле ввода `@` + часть имени + Tab вставляет файл из репозитория.
|
|
80
|
+
ревью; в поле ввода `@` + часть имени + Tab вставляет файл или папку из репозитория.
|
|
81
|
+
Кнопка микрофона в поле ввода — голосовой ввод: держите её и говорите,
|
|
82
|
+
после отпускания текст попадает в поле (отправка — как обычно). Работает
|
|
83
|
+
через Web Speech API браузера: в Chrome и Edge звук обрабатывает облачный
|
|
84
|
+
сервис браузера. В Firefox кнопки нет, как и на странице по обычному
|
|
85
|
+
`http` с другой машины (`--host 0.0.0.0`): микрофону нужен защищённый
|
|
86
|
+
контекст (`localhost` или `https`). Язык — в строке настроек чата.
|
|
81
87
|
Shift+Tab переключает режим агента, модель и режим выбираются под полем.
|
|
82
88
|
- **Подтверждения.** Запросы разрешений приходят карточкой в чат. Для
|
|
83
89
|
отдельного чата можно включить автоподтверждение (кнопка-щит) — агент
|
|
@@ -178,6 +184,22 @@ MIT, см. [LICENSE](LICENSE).
|
|
|
178
184
|
|
|
179
185
|
Сессии переживают обновление страницы и доступны из нескольких страниц браузера. История ограничена 5000 строками scrollback; после остановки сервера она теряется. Без подписчиков простаивающая сессия завершается через 15 минут, работающая или с неизвестным состоянием — не позднее часа.
|
|
180
186
|
|
|
187
|
+
Окна терминала и предпросмотра открываются из своих кнопок в доке и возвращаются к ним при сворачивании или закрытии. Переходы между размерами тоже плавные; системная настройка уменьшения движения отключает анимации.
|
|
188
|
+
|
|
189
|
+
| Сочетание | Действие |
|
|
190
|
+
| -------------- | ----------------------------------------------------------------- |
|
|
191
|
+
| Ctrl+Win+← / → | Левая / правая половина страницы |
|
|
192
|
+
| Ctrl+Win+↑ | Полный экран или возврат к обычному размеру |
|
|
193
|
+
| Ctrl+Win+↓ | Свернуть активное окно |
|
|
194
|
+
| Ctrl+Win+M | Свернуть все окна |
|
|
195
|
+
| Ctrl+Win+T | Новая вкладка терминала |
|
|
196
|
+
| Ctrl+Win+W | Закрыть активную вкладку; последняя вкладка закрывает окно |
|
|
197
|
+
| Win+Alt+Space | Голосовой ввод в выбранном чате агента, пока клавиши удерживаются |
|
|
198
|
+
|
|
199
|
+
Если активного окна нет, Ctrl+Win+↑ восстанавливает последнее свёрнутое окно в прежнем размере и положении и передаёт ему фокус.
|
|
200
|
+
|
|
201
|
+
Повтор команды текущей половины возвращает обычный размер и позицию. Перетаскивание заголовка из половины тоже возвращает обычный размер; ручной resize снимает режим половины. Сочетания работают при вводе в терминале и формах, но отключены в модальных диалогах. Win означает Super/Meta (на macOS — Command вместе с Ctrl). Системные сочетания ОС могут перехватываться до браузера.
|
|
202
|
+
|
|
181
203
|
Если платформенный бинарник PTY недоступен, терминал работает в ограниченном режиме с баннером: команды вводятся в поле под выводом, Ctrl+C прерывает команду, Ctrl+D закрывает shell. `vim`, `less` и другие интерактивные программы требуют PTY. В LAN терминал отключён. Переключатель исходных цветов отключает минимальный контраст для программ со своей палитрой.
|
|
182
204
|
|
|
183
205
|
Для разработки на другом порту backend можно передать `GITHUMAN_DEV_API=http://localhost:3848` при запуске Quasar dev-сервера.
|
|
@@ -198,7 +198,7 @@ export async function agentRoutes(app, opts) {
|
|
|
198
198
|
typedApp.get('/api/agent/files', {
|
|
199
199
|
schema: {
|
|
200
200
|
tags: TAGS,
|
|
201
|
-
summary: 'Find repository files for the context picker',
|
|
201
|
+
summary: 'Find repository files and directories for the context picker',
|
|
202
202
|
querystring: FileSearchQuery,
|
|
203
203
|
response: {
|
|
204
204
|
200: AgentFileSearchResponseSchema,
|
|
@@ -206,7 +206,7 @@ export async function agentRoutes(app, opts) {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
}, async (request) => ({
|
|
209
|
-
|
|
209
|
+
paths: await fileIndex.search(request.query.q ?? '', request.query.limit ?? DEFAULT_FILE_SEARCH_LIMIT)
|
|
210
210
|
}));
|
|
211
211
|
// One stream for every chat (ADR 0024): browsers allow ~6 connections per
|
|
212
212
|
// origin over HTTP/1.1, so a stream per session would starve the page's own
|
|
@@ -257,6 +257,12 @@ export async function agentRoutes(app, opts) {
|
|
|
257
257
|
safeSend(reply.sse, { event: 'sessions', data: {} });
|
|
258
258
|
}
|
|
259
259
|
}, Number.isInteger(lastEventId) ? lastEventId : 0);
|
|
260
|
+
// The replay can close a stream whose queue is full. `onClose` callbacks
|
|
261
|
+
// have run then, so the listener is removed here.
|
|
262
|
+
if (!reply.sse.isConnected) {
|
|
263
|
+
unsubscribe();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
260
266
|
reply.sse.onClose(unsubscribe);
|
|
261
267
|
});
|
|
262
268
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BadRequestError } from "../errors/http.js";
|
|
2
|
+
import { GitFileNotFoundError } from "../errors/git.js";
|
|
2
3
|
import { getRepositoryInfo, stagePaths, unstagePaths, discardPaths, getFilesAtRef, getFileAtRef } from "../services/git.service.js";
|
|
3
4
|
import { DiscardBody, FileContentQuery, FileContentResponseSchema, FileParams, FileTreeResponseSchema, OkSchema, OptionalPathsBody, RepositoryInfoSchema, TreeParams } from "../../shared/git/schemas.js";
|
|
4
5
|
import { ERROR_RESPONSES } from "../../shared/http/schemas.js";
|
|
@@ -95,7 +96,7 @@ export async function gitRoutes(app, opts) {
|
|
|
95
96
|
}
|
|
96
97
|
}, async (request) => {
|
|
97
98
|
const filePath = request.params['*'];
|
|
98
|
-
const { ref } = request.query;
|
|
99
|
+
const { ref, strict } = request.query;
|
|
99
100
|
if (!filePath) {
|
|
100
101
|
throw new BadRequestError('File path is required');
|
|
101
102
|
}
|
|
@@ -103,9 +104,11 @@ export async function gitRoutes(app, opts) {
|
|
|
103
104
|
let isBinary;
|
|
104
105
|
try {
|
|
105
106
|
;
|
|
106
|
-
({ content, isBinary } = await getFileAtRef(repositoryPath, ref, filePath));
|
|
107
|
+
({ content, isBinary } = await getFileAtRef(repositoryPath, ref, filePath, strict));
|
|
107
108
|
}
|
|
108
109
|
catch (err) {
|
|
110
|
+
if (err instanceof GitFileNotFoundError)
|
|
111
|
+
throw err;
|
|
109
112
|
const message = err instanceof Error ? err.message : 'Failed to read file';
|
|
110
113
|
throw new BadRequestError(message, { cause: err });
|
|
111
114
|
}
|
|
@@ -11,7 +11,8 @@ import * as acp from '@agentclientprotocol/sdk';
|
|
|
11
11
|
import { mapConfigOptions, mapPermissionRequest, mapSessionUpdate } from "../../adapters/agents/event-mapper.js";
|
|
12
12
|
/** `npx` may have to download the adapter first. */
|
|
13
13
|
const START_TIMEOUT_MS = 90_000;
|
|
14
|
-
|
|
14
|
+
/** Events that one session keeps for a client that joins late or reconnects. */
|
|
15
|
+
export const MAX_BUFFERED_EVENTS = 5_000;
|
|
15
16
|
const STDERR_TAIL_CHARS = 2_000;
|
|
16
17
|
/** How long a closed connection waits for the `exit` event that carries the reason. */
|
|
17
18
|
const EXIT_GRACE_MS = 500;
|
|
@@ -2,10 +2,11 @@ import { MAX_ATTACHMENT_BYTES } from "../../../shared/agents/constants.js";
|
|
|
2
2
|
import { AgentContextError } from "../../errors/agents.js";
|
|
3
3
|
import { errorMessage } from "../../../shared/utils/error-message.js";
|
|
4
4
|
import { formatDiffFile } from "../../../shared/agents/context-format.js";
|
|
5
|
+
import { withoutTrailingSlash } from "../../../shared/agents/mention-paths.js";
|
|
5
6
|
import { randomUUID } from 'node:crypto';
|
|
6
7
|
import { pathToFileURL } from 'node:url';
|
|
7
|
-
import { mkdir, stat, writeFile } from 'node:fs/promises';
|
|
8
|
-
import { join } from 'node:path';
|
|
8
|
+
import { mkdir, realpath, stat, writeFile } from 'node:fs/promises';
|
|
9
|
+
import { join, relative, resolve, sep } from 'node:path';
|
|
9
10
|
import { getStagedDiff, getUnstagedDiff } from "../diff.service.js";
|
|
10
11
|
import { exportAsMarkdown } from "../export.service.js";
|
|
11
12
|
import { resolveWithinRepo } from "../git.service.js";
|
|
@@ -57,6 +58,19 @@ async function buildDiffItem(item, deps) {
|
|
|
57
58
|
}
|
|
58
59
|
return embed(deps, `githuman://diff/${item.source}/${item.path ?? ''}`, `Diff (${item.source}${item.path === undefined ? '' : `, ${item.path}`}):`, 'text/x-diff', selected.map(formatDiffFile).join('\n'));
|
|
59
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* `resolveWithinRepo` checks the path as text, but `stat` follows a symbolic
|
|
63
|
+
* link. A link that points out of the repository must not reach the agent.
|
|
64
|
+
*/
|
|
65
|
+
async function assertRealPathInRepo(repositoryPath, absolute, path) {
|
|
66
|
+
const [root, target] = await Promise.all([
|
|
67
|
+
realpath(repositoryPath),
|
|
68
|
+
realpath(absolute)
|
|
69
|
+
]);
|
|
70
|
+
if (target !== root && !target.startsWith(root + sep)) {
|
|
71
|
+
throw new AgentContextError(`"${path}" points out of the repository`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
60
74
|
async function buildFileItem(item, deps) {
|
|
61
75
|
let absolute;
|
|
62
76
|
try {
|
|
@@ -69,12 +83,42 @@ async function buildFileItem(item, deps) {
|
|
|
69
83
|
if (!info?.isFile()) {
|
|
70
84
|
throw new AgentContextError(`"${item.path}" is not a file in the repository`);
|
|
71
85
|
}
|
|
86
|
+
await assertRealPathInRepo(deps.repositoryPath, absolute, item.path);
|
|
72
87
|
return {
|
|
73
88
|
type: 'resource_link',
|
|
74
89
|
uri: pathToFileURL(absolute).href,
|
|
75
90
|
name: item.path
|
|
76
91
|
};
|
|
77
92
|
}
|
|
93
|
+
async function buildDirectoryItem(item, deps) {
|
|
94
|
+
const path = withoutTrailingSlash(item.path);
|
|
95
|
+
let absolute;
|
|
96
|
+
try {
|
|
97
|
+
absolute = resolveWithinRepo(deps.repositoryPath, path);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
throw asContextError(error);
|
|
101
|
+
}
|
|
102
|
+
// The agent runs in the repository root already, so a link to it says nothing.
|
|
103
|
+
if (absolute === resolve(deps.repositoryPath)) {
|
|
104
|
+
throw new AgentContextError('The repository root cannot be a context item');
|
|
105
|
+
}
|
|
106
|
+
const info = await stat(absolute).catch(() => null);
|
|
107
|
+
if (!info?.isDirectory()) {
|
|
108
|
+
throw new AgentContextError(`"${path}" is not a directory in the repository`);
|
|
109
|
+
}
|
|
110
|
+
await assertRealPathInRepo(deps.repositoryPath, absolute, path);
|
|
111
|
+
// ACP has no type for a directory link. The trailing `/` in the URI and the
|
|
112
|
+
// name is the only sign for the agent that the link names a directory.
|
|
113
|
+
const name = relative(resolve(deps.repositoryPath), absolute)
|
|
114
|
+
.split(sep)
|
|
115
|
+
.join('/');
|
|
116
|
+
return {
|
|
117
|
+
type: 'resource_link',
|
|
118
|
+
uri: pathToFileURL(absolute + sep).href,
|
|
119
|
+
name: `${name}/`
|
|
120
|
+
};
|
|
121
|
+
}
|
|
78
122
|
async function buildReviewItem(item, deps) {
|
|
79
123
|
let markdown;
|
|
80
124
|
try {
|
|
@@ -125,6 +169,9 @@ function buildItem(item, deps) {
|
|
|
125
169
|
if (item.kind === 'file') {
|
|
126
170
|
return buildFileItem(item, deps);
|
|
127
171
|
}
|
|
172
|
+
if (item.kind === 'directory') {
|
|
173
|
+
return buildDirectoryItem(item, deps);
|
|
174
|
+
}
|
|
128
175
|
if (item.kind === 'attachment') {
|
|
129
176
|
return buildAttachmentItem(item, deps);
|
|
130
177
|
}
|
|
@@ -2,9 +2,10 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { getFilesAtRef } from "../git.service.js";
|
|
4
4
|
import { DEFAULT_FILE_SEARCH_LIMIT } from "../../../shared/agents/constants.js";
|
|
5
|
-
import {
|
|
5
|
+
import { rankPaths } from "../../../shared/agents/file-search.js";
|
|
6
|
+
import { withDirectories } from "../../../shared/agents/mention-paths.js";
|
|
6
7
|
/**
|
|
7
|
-
* The repository's file list for `@` mentions. Read once from `git ls-files`
|
|
8
|
+
* The repository's file and directory list for `@` mentions. Read once from `git ls-files`
|
|
8
9
|
* and filtered in memory — the query never reaches a git argument — and
|
|
9
10
|
* dropped whenever the working tree changes.
|
|
10
11
|
*/
|
|
@@ -26,6 +27,7 @@ export function createFileIndex(repositoryPath, eventBus) {
|
|
|
26
27
|
if (!loading) {
|
|
27
28
|
const started = generation;
|
|
28
29
|
loading = getFilesAtRef(repositoryPath, 'WORKTREE')
|
|
30
|
+
.then(withDirectories)
|
|
29
31
|
.then(list => {
|
|
30
32
|
if (started === generation) {
|
|
31
33
|
cached = list;
|
|
@@ -40,10 +42,11 @@ export function createFileIndex(repositoryPath, eventBus) {
|
|
|
40
42
|
}
|
|
41
43
|
return {
|
|
42
44
|
async search(query, limit = DEFAULT_FILE_SEARCH_LIMIT) {
|
|
43
|
-
const ranked =
|
|
45
|
+
const ranked = rankPaths(await files(), query);
|
|
44
46
|
const found = [];
|
|
45
47
|
for (const path of ranked) {
|
|
46
|
-
// `ls-files --cached` still lists files deleted from the working tree
|
|
48
|
+
// `ls-files --cached` still lists files deleted from the working tree,
|
|
49
|
+
// so a directory can also be gone.
|
|
47
50
|
if (existsSync(join(repositoryPath, path))) {
|
|
48
51
|
found.push(path);
|
|
49
52
|
if (found.length >= limit) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { execFile, spawn } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import { basename, resolve, sep } from 'node:path';
|
|
4
|
+
import { basename, posix, resolve, sep } from 'node:path';
|
|
5
5
|
import { simpleGit } from 'simple-git';
|
|
6
|
+
import { GitFileNotFoundError } from "../errors/git.js";
|
|
6
7
|
import { isBinaryBuffer } from "../utils/text.js";
|
|
7
8
|
const execFileAsync = promisify(execFile);
|
|
8
9
|
/**
|
|
@@ -48,6 +49,31 @@ function objectSpecFor(ref, path) {
|
|
|
48
49
|
// the injection this would otherwise guard against.
|
|
49
50
|
return ref === 'INDEX' ? `:${path}` : `${ref}:${path}`;
|
|
50
51
|
}
|
|
52
|
+
/** `ENOENT` and `ENOTDIR` both mean that the file does not exist. */
|
|
53
|
+
function isMissingPathError(error) {
|
|
54
|
+
return (!!error &&
|
|
55
|
+
typeof error === 'object' &&
|
|
56
|
+
'code' in error &&
|
|
57
|
+
(error.code === 'ENOENT' || error.code === 'ENOTDIR'));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Checks one path with `ls-tree` instead of listing the whole tree. A failing
|
|
61
|
+
* `ls-tree` means the ref is invalid, so the path is reported as present and
|
|
62
|
+
* the caller keeps the original error.
|
|
63
|
+
*/
|
|
64
|
+
async function pathExistsAtRef(repoPath, ref, path) {
|
|
65
|
+
const normalized = posix.normalize(path);
|
|
66
|
+
try {
|
|
67
|
+
const args = ref === 'INDEX'
|
|
68
|
+
? ['ls-files', '-z', '--', `:(literal)${normalized}`]
|
|
69
|
+
: ['ls-tree', '-z', ref, '--', normalized];
|
|
70
|
+
const { stdout } = await execFileAsync('git', args, { cwd: repoPath });
|
|
71
|
+
return stdout.length > 0;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
51
77
|
/**
|
|
52
78
|
* Reads a file's content at a given git ref.
|
|
53
79
|
*
|
|
@@ -58,7 +84,7 @@ function objectSpecFor(ref, path) {
|
|
|
58
84
|
* HEAD version), returns empty content rather than throwing — the caller
|
|
59
85
|
* treats this as "the file did not exist on this side of the diff".
|
|
60
86
|
*/
|
|
61
|
-
export async function getFileAtRef(repoPath, ref, path) {
|
|
87
|
+
export async function getFileAtRef(repoPath, ref, path, strict = false) {
|
|
62
88
|
if (ref === 'WORKTREE') {
|
|
63
89
|
try {
|
|
64
90
|
const absolutePath = resolveWithinRepo(repoPath, path);
|
|
@@ -66,7 +92,14 @@ export async function getFileAtRef(repoPath, ref, path) {
|
|
|
66
92
|
const isBinary = isBinaryBuffer(buffer);
|
|
67
93
|
return { content: isBinary ? '' : buffer.toString('utf-8'), isBinary };
|
|
68
94
|
}
|
|
69
|
-
catch {
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (strict) {
|
|
97
|
+
if (isMissingPathError(error))
|
|
98
|
+
throw new GitFileNotFoundError('File was deleted or moved', {
|
|
99
|
+
cause: error
|
|
100
|
+
});
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
70
103
|
return { content: '', isBinary: false };
|
|
71
104
|
}
|
|
72
105
|
}
|
|
@@ -83,7 +116,14 @@ export async function getFileAtRef(repoPath, ref, path) {
|
|
|
83
116
|
isBinary
|
|
84
117
|
};
|
|
85
118
|
}
|
|
86
|
-
catch {
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (strict) {
|
|
121
|
+
if (!(await pathExistsAtRef(repoPath, ref, path)))
|
|
122
|
+
throw new GitFileNotFoundError('File was deleted or moved', {
|
|
123
|
+
cause: error
|
|
124
|
+
});
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
87
127
|
return { content: '', isBinary: false };
|
|
88
128
|
}
|
|
89
129
|
}
|
package/dist/server/utils/sse.js
CHANGED
|
@@ -1,11 +1,82 @@
|
|
|
1
|
+
// Each connection must wait for backpressure before sending its next message.
|
|
2
|
+
const SEND_QUEUES = new WeakMap();
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
4
|
+
* The maximum number of messages in the send queue of one connection. On a
|
|
5
|
+
* reconnect the agent stream replays every session buffer at once:
|
|
6
|
+
* MAX_AGENT_SESSIONS × MAX_BUFFERED_EVENTS, plus a `gap` and a `state` for
|
|
7
|
+
* each session. A lower limit closes the stream before its first send, and the
|
|
8
|
+
* client then reconnects in a loop. The limit is about twice that replay, so
|
|
9
|
+
* live events have room. This count bounds memory. There is no byte limit:
|
|
10
|
+
* most queued items point to events that the session buffers hold already (#85).
|
|
5
11
|
*/
|
|
12
|
+
export const MAX_QUEUED_MESSAGES = 50_000;
|
|
13
|
+
/**
|
|
14
|
+
* A send that has not finished after this time means that the client stopped
|
|
15
|
+
* reading. The check runs when a new message arrives, so it closes a dead
|
|
16
|
+
* connection before the count limit does. A slow client that still reads
|
|
17
|
+
* finishes each send sooner. The
|
|
18
|
+
* check uses `Date.now()`: a jump of the system clock can make a false stall,
|
|
19
|
+
* and the client then only reconnects.
|
|
20
|
+
*/
|
|
21
|
+
export const STALL_TIMEOUT_MS = 30_000;
|
|
22
|
+
/**
|
|
23
|
+
* Closes a connection that does not read, and drops its queue. Dropping only
|
|
24
|
+
* some messages would hide the loss from the client. The client reconnects by
|
|
25
|
+
* itself: the agent stream resumes from `Last-Event-ID` or gets `gap`, and
|
|
26
|
+
* `/api/events` refetches after the reconnect. Nothing is logged: the Fastify
|
|
27
|
+
* logger is off, and the reconnect is the normal recovery (#85).
|
|
28
|
+
*/
|
|
29
|
+
function dropConnection(sse, queue) {
|
|
30
|
+
if (queue.closed)
|
|
31
|
+
return;
|
|
32
|
+
queue.closed = true;
|
|
33
|
+
queue.messages.length = 0;
|
|
34
|
+
try {
|
|
35
|
+
sse.close();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// The connection is already gone.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function flush(sse, queue) {
|
|
42
|
+
queue.sending = true;
|
|
43
|
+
try {
|
|
44
|
+
while (!queue.closed && sse.isConnected && queue.messages.length) {
|
|
45
|
+
queue.sendStartedAt = Date.now();
|
|
46
|
+
await sse.send(queue.messages.shift());
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// A disconnected client must not cause an unhandled rejection.
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
queue.messages.length = 0;
|
|
54
|
+
queue.sending = false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Queue messages in order without concurrent writes to a slow client. */
|
|
6
58
|
export function safeSend(sse, message) {
|
|
7
|
-
if (!sse.isConnected)
|
|
59
|
+
if (!sse.isConnected)
|
|
60
|
+
return;
|
|
61
|
+
let queue = SEND_QUEUES.get(sse);
|
|
62
|
+
if (!queue) {
|
|
63
|
+
queue = { messages: [], sending: false, closed: false, sendStartedAt: 0 };
|
|
64
|
+
SEND_QUEUES.set(sse, queue);
|
|
65
|
+
const connectionQueue = queue;
|
|
66
|
+
sse.onClose?.(() => {
|
|
67
|
+
connectionQueue.closed = true;
|
|
68
|
+
connectionQueue.messages.length = 0;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (queue.closed)
|
|
72
|
+
return;
|
|
73
|
+
// The queue grows only here, so the limits are checked only here.
|
|
74
|
+
if (queue.messages.length >= MAX_QUEUED_MESSAGES ||
|
|
75
|
+
(queue.sending && Date.now() - queue.sendStartedAt > STALL_TIMEOUT_MS)) {
|
|
76
|
+
dropConnection(sse, queue);
|
|
8
77
|
return;
|
|
9
78
|
}
|
|
10
|
-
|
|
79
|
+
queue.messages.push(message);
|
|
80
|
+
if (!queue.sending)
|
|
81
|
+
void flush(sse, queue);
|
|
11
82
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDirectoryPath, withoutTrailingSlash } from "./mention-paths.js";
|
|
1
2
|
function isSubsequence(needle, haystack) {
|
|
2
3
|
let at = 0;
|
|
3
4
|
for (const char of haystack) {
|
|
@@ -13,7 +14,16 @@ function isSubsequence(needle, haystack) {
|
|
|
13
14
|
/** Lower is better; undefined = no match. */
|
|
14
15
|
function score(path, query) {
|
|
15
16
|
const lower = path.toLowerCase();
|
|
16
|
-
|
|
17
|
+
// A query that ends with `/` names a directory: `web/` or `src/web/` puts
|
|
18
|
+
// `src/web/` first, above the files in it.
|
|
19
|
+
if (query.endsWith('/') && isDirectoryPath(lower) && lower.endsWith(query)) {
|
|
20
|
+
const before = lower.length - query.length;
|
|
21
|
+
if (before === 0 || lower[before - 1] === '/')
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
// The name of a directory is taken without the `/`: with it, the name is empty.
|
|
25
|
+
const name = withoutTrailingSlash(lower);
|
|
26
|
+
const base = name.slice(name.lastIndexOf('/') + 1);
|
|
17
27
|
if (base === query)
|
|
18
28
|
return 0;
|
|
19
29
|
if (base.startsWith(query))
|
|
@@ -27,21 +37,23 @@ function score(path, query) {
|
|
|
27
37
|
return undefined;
|
|
28
38
|
}
|
|
29
39
|
/**
|
|
30
|
-
* Orders `
|
|
31
|
-
*
|
|
32
|
-
*
|
|
40
|
+
* Orders `paths` by how well they match `query`: name first (exact, prefix,
|
|
41
|
+
* substring), then anywhere in the path, then as scattered letters. Ties go
|
|
42
|
+
* to a file before a directory, then to the shorter path. An empty query
|
|
43
|
+
* matches everything, so files lead the list and short directories do not.
|
|
33
44
|
*/
|
|
34
|
-
export function
|
|
45
|
+
export function rankPaths(paths, query) {
|
|
35
46
|
const needle = query.trim().toLowerCase();
|
|
36
47
|
const scored = [];
|
|
37
|
-
for (const path of
|
|
48
|
+
for (const path of paths) {
|
|
38
49
|
const rank = needle === '' ? 0 : score(path, needle);
|
|
39
50
|
if (rank !== undefined) {
|
|
40
|
-
scored.push({ path, rank });
|
|
51
|
+
scored.push({ path, rank, directory: isDirectoryPath(path) ? 1 : 0 });
|
|
41
52
|
}
|
|
42
53
|
}
|
|
43
54
|
return scored
|
|
44
55
|
.sort((a, b) => a.rank - b.rank ||
|
|
56
|
+
a.directory - b.directory ||
|
|
45
57
|
a.path.length - b.path.length ||
|
|
46
58
|
a.path.localeCompare(b.path))
|
|
47
59
|
.map(entry => entry.path);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A mentioned path that ends with `/` names a directory, as in agent CLIs.
|
|
3
|
+
* The context item keeps the path without that `/` (#80).
|
|
4
|
+
*/
|
|
5
|
+
export function isDirectoryPath(path) {
|
|
6
|
+
return path.endsWith('/');
|
|
7
|
+
}
|
|
8
|
+
/** The path without trailing `/`: the form that a `directory` context item holds. */
|
|
9
|
+
export function withoutTrailingSlash(path) {
|
|
10
|
+
return path.replace(/\/+$/, '');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The files and every directory that holds one of them, a directory as `a/b/`.
|
|
14
|
+
* `git ls-files --others` already gives an untracked nested repository as
|
|
15
|
+
* `dir/`, so a path with a trailing `/` is a directory too.
|
|
16
|
+
*/
|
|
17
|
+
export function withDirectories(paths) {
|
|
18
|
+
const directories = new Set();
|
|
19
|
+
for (const path of paths) {
|
|
20
|
+
const parts = withoutTrailingSlash(path).split('/');
|
|
21
|
+
const last = isDirectoryPath(path) ? parts.length : parts.length - 1;
|
|
22
|
+
for (let end = 1; end <= last; end++) {
|
|
23
|
+
directories.add(`${parts.slice(0, end).join('/')}/`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
directories.delete('/');
|
|
27
|
+
return [...paths.filter(path => !isDirectoryPath(path)), ...directories];
|
|
28
|
+
}
|
|
29
|
+
/** Name, parent path and kind of a mentioned path, for chips and the popup. */
|
|
30
|
+
export function mentionParts(path) {
|
|
31
|
+
const directory = isDirectoryPath(path);
|
|
32
|
+
const bare = withoutTrailingSlash(path);
|
|
33
|
+
const at = bare.lastIndexOf('/');
|
|
34
|
+
const name = at === -1 ? bare : bare.slice(at + 1);
|
|
35
|
+
return {
|
|
36
|
+
name: directory ? `${name}/` : name,
|
|
37
|
+
parent: at === -1 ? '' : bare.slice(0, at),
|
|
38
|
+
directory
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -28,7 +28,7 @@ export const AutoApproveBody = Type.Object({
|
|
|
28
28
|
export const FileSearchQuery = Type.Object({
|
|
29
29
|
q: Type.Optional(Type.String({
|
|
30
30
|
maxLength: 200,
|
|
31
|
-
description: 'Fuzzy text to find in paths. Empty lists files.'
|
|
31
|
+
description: 'Fuzzy text to find in paths. Empty lists files first.'
|
|
32
32
|
})),
|
|
33
33
|
limit: Type.Optional(Type.Integer({
|
|
34
34
|
minimum: 1,
|
|
@@ -52,6 +52,15 @@ export const ContextItem = Type.Union([
|
|
|
52
52
|
description: 'Repository-relative path. The agent reads the file.'
|
|
53
53
|
})
|
|
54
54
|
}, { description: 'A link to a repository file.' }),
|
|
55
|
+
Type.Object({
|
|
56
|
+
kind: Type.Literal('directory', {
|
|
57
|
+
description: 'A repository directory.'
|
|
58
|
+
}),
|
|
59
|
+
path: Type.String({
|
|
60
|
+
minLength: 1,
|
|
61
|
+
description: 'Repository-relative path without a trailing slash. The agent reads the directory.'
|
|
62
|
+
})
|
|
63
|
+
}, { description: 'A link to a repository directory.' }),
|
|
55
64
|
Type.Object({
|
|
56
65
|
kind: Type.Literal('review', { description: 'A review.' }),
|
|
57
66
|
reviewId: Type.String({ description: 'Review id.' })
|
|
@@ -126,10 +135,10 @@ export const AgentSessionInfoSchema = Type.Object({
|
|
|
126
135
|
}))
|
|
127
136
|
}, { description: 'A chat session.' });
|
|
128
137
|
export const AgentFileSearchResponseSchema = Type.Object({
|
|
129
|
-
|
|
130
|
-
description: 'Repository-relative paths, best match first.'
|
|
138
|
+
paths: Type.Array(Type.String(), {
|
|
139
|
+
description: 'Repository-relative paths, best match first. A directory path ends with a slash.'
|
|
131
140
|
})
|
|
132
|
-
}, { description: 'Files for the context picker.' });
|
|
141
|
+
}, { description: 'Files and directories for the context picker.' });
|
|
133
142
|
export const AgentEventsHeaders = Type.Object({
|
|
134
143
|
'last-event-id': Type.Optional(Type.String({
|
|
135
144
|
description: 'Last event id that the client got. Events after it come again.'
|
|
@@ -44,7 +44,10 @@ export const FileContentQuery = Type.Object({
|
|
|
44
44
|
ref: Type.String({
|
|
45
45
|
minLength: 1,
|
|
46
46
|
description: 'Commit, branch or tag. INDEX reads the index, WORKTREE the file on disk.'
|
|
47
|
-
})
|
|
47
|
+
}),
|
|
48
|
+
strict: Type.Optional(Type.Boolean({
|
|
49
|
+
description: 'Report a missing file as 404 instead of empty content.'
|
|
50
|
+
}))
|
|
48
51
|
});
|
|
49
52
|
export const OptionalPathsBody = Type.Object({
|
|
50
53
|
paths: Type.Optional(Type.Array(Type.String(), {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/typescript-Utq2Cl8c.js","assets/typescript-j_1H8WHN.js","assets/javascript-Yelw-5ZN.js","assets/javascript-BzbQS41l.js","assets/vue-CSBlZ1UP.js","assets/css-LbU1hoFO.js","assets/html-BcACZWSP.js","assets/json-B88Oqtu5.js","assets/json-CaljABEy.js","assets/css-CdtkT07m.js","assets/scss-DHtrkMkT.js","assets/html-DDNsd9lV.js","assets/core-C37KF-j0.js","assets/rolldown-runtime-Dd_uD5pT.js","assets/engine-oniguruma-B4iNeJbd.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{J as e,L as t,P as n,S as r,_ as i,
|
|
2
|
+
import{J as e,L as t,P as n,S as r,_ as i,b as a,ct as o,l as s,ot as c,pt as l,s as u,w as d}from"./runtime-core.esm-bundler-BKFI1w28.js";import{D as f,O as p,_ as m,j as h,t as g}from"./QBtn-CzrOO1zA.js";import{t as _}from"./create-BSmXD9Zr.js";import{F as v}from"./index-BqedItFI.js";import{n as y}from"./vue-i18n.runtime-BpRrzZrT.js";import{n as b}from"./pinia-DCsnCHsH.js";import{d as x,f as S,l as C,o as ee,s as w,u as T}from"./use-server-events-znzHKZZx.js";function E(e){if(e.length<2||e[0]!==`"`||e[e.length-1]!==`"`)return e;let t=e.slice(1,-1),n=[];for(let e=0;e<t.length;e++){let r=t[e];r===`\\`&&/^[0-7]{3}$/.test(t.slice(e+1,e+4))?(n.push(parseInt(t.slice(e+1,e+4),8)),e+=3):r===`\\`&&t[e+1]===`"`?(n.push(34),e+=1):r===`\\`&&t[e+1]===`\\`?(n.push(92),e+=1):n.push((r??``).charCodeAt(0))}return new TextDecoder(`utf-8`).decode(new Uint8Array(n))}function D(e){return e.newPath||e.oldPath}function O(e,t){return`${e}:${t}`}function k(e,t){let n=new Map,r=0;function i(e){let t=n.get(e);if(t)return n.delete(e),n.set(e,t),t.value}function a(i,a){o(i);let s=t(a);n.set(i,{value:a,weight:s}),r+=s;for(let[t,i]of n){if(r<=e||n.size<=1)break;n.delete(t),r-=i.weight}}function o(e){let t=n.get(e);t&&(n.delete(e),r-=t.weight)}return{get:i,set:a,remove:o,size:()=>n.size}}var A={typescript:()=>v(()=>import(`./typescript-Utq2Cl8c.js`),__vite__mapDeps([0,1])),tsx:()=>v(()=>import(`./tsx-udAQXfEw.js`),[]),javascript:()=>v(()=>import(`./javascript-Yelw-5ZN.js`),__vite__mapDeps([2,3])),jsx:()=>v(()=>import(`./jsx-Bz0zcwM4.js`),[]),vue:()=>v(()=>import(`./vue-CSBlZ1UP.js`),__vite__mapDeps([4,5,3,6,7,1])),json:()=>v(()=>import(`./json-CaljABEy.js`),__vite__mapDeps([8,7])),markdown:()=>v(()=>import(`./markdown-BYOwaDjH.js`),[]),css:()=>v(()=>import(`./css-CdtkT07m.js`),__vite__mapDeps([9,5])),scss:()=>v(()=>import(`./scss-DHtrkMkT.js`),__vite__mapDeps([10,5])),html:()=>v(()=>import(`./html-DDNsd9lV.js`),__vite__mapDeps([11,6,5,3])),yaml:()=>v(()=>import(`./yaml-rwi0_p6S.js`),[]),bash:()=>v(()=>import(`./bash-CLZ0U2zV.js`),[]),python:()=>v(()=>import(`./python-gzcpVVnB.js`),[]),go:()=>v(()=>import(`./go-rLFTqkRN.js`),[]),rust:()=>v(()=>import(`./rust-Cfkwpbl8.js`),[]),java:()=>v(()=>import(`./java-BXcb2rRD.js`),[]),kotlin:()=>v(()=>import(`./kotlin-DhhofPvG.js`),[])},j={light:()=>v(()=>import(`./github-light-EUqPIrTm.js`),[]),dark:()=>v(()=>import(`./github-dark-C-LZuMrd.js`),[])},te={light:`github-light`,dark:`github-dark`},M=null,N=new Set,P=new Map;function F(e){return A[e]!==void 0}async function ne(e,t){try{await e.loadLanguage(A[t]()),N.add(t)}finally{P.delete(t)}}async function re(e){M||=(async()=>{let[{createHighlighterCore:e},{createOnigurumaEngine:t}]=await Promise.all([v(()=>import(`./core-C37KF-j0.js`),__vite__mapDeps([12,13])),v(()=>import(`./engine-oniguruma-B4iNeJbd.js`),__vite__mapDeps([14,13]))]);return e({themes:[j.light(),j.dark()],langs:[],engine:t(()=>v(()=>import(`./wasm-BnjxR4X6.js`),[]))})})();let t=await M;if(!N.has(e)){let n=P.get(e);n||(n=ne(t,e),P.set(e,n)),await n}return t}async function ie(e,t,n={}){if(!F(e)||t.length===0)return`failed`;let r=n.documents??[{length:t.length,skip:0}];if(r.reduce((e,t)=>e+t.length,0)!==t.length)return`failed`;let{signal:i}=n;try{let a=await re(e),o=0,s=0,c=!0;for(let l of r){let r,u=Math.max(1,n.sliceSize??l.length);for(let d=0;d<l.length;d+=u){if(c||await n.yieldBetween?.(),c=!1,i?.aborted)return`aborted`;let f=Math.min(d+u,l.length),p=a.codeToTokensWithThemes(t.slice(o+d,o+f).join(`
|
|
3
3
|
`),{lang:e,themes:te,...r?{grammarState:r}:{}});r=a.getLastGrammarState(p);let m=Math.max(d,l.skip);f<=m||(n.onSlice?.(p.slice(m-d).map(e=>e.map(e=>({content:e.content,colorLight:e.variants.light?.color,colorDark:e.variants.dark?.color}))),s),s+=f-m)}o+=l.length}return`done`}catch{return`failed`}}var I=null,L=!1,ae=1,R=new Map;function z(){return typeof Worker<`u`&&!L}function oe(){let e=new Worker(new URL(`/assets/highlight.worker-BHCdEX06.js`,``+import.meta.url),{type:`module`});return e.addEventListener(`message`,e=>{let t=e.data,n=R.get(t.id);n&&(t.type===`slice`?n.onSlice(t.tokens,t.start):(R.delete(t.id),n.finish(t.ok?`done`:`failed`)))}),e.addEventListener(`error`,t=>{console.error(`The highlight worker failed, the main thread does the work now`,t),L=!0;for(let e of R.values())e.finish(`failed`);R.clear(),e.terminate(),I=null}),e}function B(e,t){e.postMessage(t)}function se(e,t,n){let{signal:r}=n;if(r?.aborted)return Promise.resolve(`aborted`);if(!I)try{I=oe()}catch(e){return console.error(`The highlight worker did not start`,e),L=!0,Promise.resolve(`unsent`)}let i=I;return new Promise(a=>{let o=ae++,s=()=>{R.delete(o)&&(I&&B(I,{type:`cancel`,id:o}),a(`aborted`))};R.set(o,{onSlice:(e,t)=>n.onSlice?.(e,t),finish:e=>{r?.removeEventListener(`abort`,s),a(e)}});try{B(i,{type:`tokenize`,id:o,lang:e,lines:Array.from(t),...n.documents?{documents:n.documents.map(e=>({...e}))}:{},sliceSize:n.sliceSize})}catch(e){console.error(`The highlight worker did not get the request`,e),R.delete(o),a(`unsent`);return}r?.addEventListener(`abort`,s,{once:!0})})}function ce(){return typeof MessageChannel>`u`?new Promise(e=>setTimeout(e,0)):new Promise(e=>{let{port1:t,port2:n}=new MessageChannel;t.addEventListener(`message`,()=>{t.close(),e()},{once:!0}),t.start(),n.postMessage(null)})}var V=`import { ref, type Ref } from 'vue'
|
|
4
4
|
import * as path from 'node:path'
|
|
5
5
|
// A comment with a TODO and a URL: https://example.com
|
|
@@ -90,4 +90,4 @@ Some *emphasis*, **strong** text, \`inline code\` and a [link](https://example.c
|
|
|
90
90
|
const answer: number = 42
|
|
91
91
|
\`\`\`
|
|
92
92
|
`,typescript:V,javascript:V,tsx:V,jsx:V};function ue(e){return(le[e]??`x`).split(`
|
|
93
|
-
`)}var de=2e4,U=100,fe={ts:`typescript`,tsx:`tsx`,js:`javascript`,jsx:`jsx`,mjs:`javascript`,cjs:`javascript`,vue:`vue`,json:`json`,md:`markdown`,css:`css`,scss:`scss`,html:`html`,yml:`yaml`,yaml:`yaml`,sh:`bash`,py:`python`,go:`go`,rs:`rust`,java:`java`,kt:`kotlin`,kts:`kotlin`};function W(e){let t=e.split(`.`);return t.length<2?`text`:fe[t.pop().toLowerCase()]??`text`}function pe(e){return F(W(e))}function G(e,t,n,r,i){return ie(e,t,{documents:n,sliceSize:U,yieldBetween:ce,signal:r,onSlice:i})}async function K(e,t,n,r,i){let a=[],o=(e,t)=>{a.splice(t,e.length,...e),r?.(a.slice())};if(!z())return q(await G(e,t,i,n,o),a);let s=await se(e,t,{sliceSize:U,documents:i,signal:n,onSlice:o});return(s===`unsent`||s===`failed`&&!z())&&(s=await G(e,t,i,n,o)),q(s,a)}function q(e,t){return e===`done`?t:e===`aborted`?void 0:null}var J=new Set;async function me(e){await K(e,ue(e)).catch(()=>null)===null&&J.delete(e)}function he(e){if(!z())return;let t=new Set(e.map(W).filter(F));for(let e of t)J.has(e)||(J.add(e),me(e))}var Y=k(de,e=>e?.length??1),X=Promise.resolve();function ge(e){let t=X.then(()=>new Promise(e=>setTimeout(e,0))).then(e);return X=t.catch(()=>void 0),t}function _e(e,t,n,r,i,a){return ge(async()=>{let o=Y.get(e);if(o!==void 0)return o;if(r?.aborted)return;let s=n(),c=await K(W(t),s,r,i,a?.());if(c!==void 0)return Y.set(e,c),c})}function ve(e){return Y.get(e)}function Z(e){return{...e,oldPath:E(e.oldPath),newPath:E(e.newPath)}}function ye(e){let{signature:t,...n}=e;return{...n,hunks:[]}}function Q(e,t,n){let r=new Map(e.map(e=>[D(e),e])),i=new Map;return{files:n.map(e=>{let n=D(e);i.set(n,e.signature);let a=r.get(n);return a&&t.get(n)===e.signature?a:ye(e)}),signatures:i}}var be=b(`diff`,()=>{let e=
|
|
93
|
+
`)}var de=2e4,U=100,fe={ts:`typescript`,tsx:`tsx`,js:`javascript`,jsx:`jsx`,mjs:`javascript`,cjs:`javascript`,vue:`vue`,json:`json`,md:`markdown`,css:`css`,scss:`scss`,html:`html`,yml:`yaml`,yaml:`yaml`,sh:`bash`,py:`python`,go:`go`,rs:`rust`,java:`java`,kt:`kotlin`,kts:`kotlin`};function W(e){let t=e.split(`.`);return t.length<2?`text`:fe[t.pop().toLowerCase()]??`text`}function pe(e){return F(W(e))}function G(e,t,n,r,i){return ie(e,t,{documents:n,sliceSize:U,yieldBetween:ce,signal:r,onSlice:i})}async function K(e,t,n,r,i){let a=[],o=(e,t)=>{a.splice(t,e.length,...e),r?.(a.slice())};if(!z())return q(await G(e,t,i,n,o),a);let s=await se(e,t,{sliceSize:U,documents:i,signal:n,onSlice:o});return(s===`unsent`||s===`failed`&&!z())&&(s=await G(e,t,i,n,o)),q(s,a)}function q(e,t){return e===`done`?t:e===`aborted`?void 0:null}var J=new Set;async function me(e){await K(e,ue(e)).catch(()=>null)===null&&J.delete(e)}function he(e){if(!z())return;let t=new Set(e.map(W).filter(F));for(let e of t)J.has(e)||(J.add(e),me(e))}var Y=k(de,e=>e?.length??1),X=Promise.resolve();function ge(e){let t=X.then(()=>new Promise(e=>setTimeout(e,0))).then(e);return X=t.catch(()=>void 0),t}function _e(e,t,n,r,i,a){return ge(async()=>{let o=Y.get(e);if(o!==void 0)return o;if(r?.aborted)return;let s=n(),c=await K(W(t),s,r,i,a?.());if(c!==void 0)return Y.set(e,c),c})}function ve(e){return Y.get(e)}function Z(e){return{...e,oldPath:E(e.oldPath),newPath:E(e.newPath)}}function ye(e){let{signature:t,...n}=e;return{...n,hunks:[]}}function Q(e,t,n){let r=new Map(e.map(e=>[D(e),e])),i=new Map;return{files:n.map(e=>{let n=D(e);i.set(n,e.signature);let a=r.get(n);return a&&t.get(n)===e.signature?a:ye(e)}),signatures:i}}var be=b(`diff`,()=>{let e=c([]),t=c([]),n=new Map,r=new Map,i=c(!1),a=c(!1),s=c(null),l=u(()=>i.value&&!a.value),d=u(()=>[...e.value,...t.value].map(e=>e.newPath||e.oldPath)),f=o(new Map),p=o(new Map),m=new Map;function h(n){return n===`staged`?e.value:t.value}function g(e,t){return f.value.get(O(e,D(t)))?.file}function _(e,t){return f.value.get(O(e,D(t)))?.for===t}function v(e,t){let n=p.value.get(O(e,D(t)));return n?.for===t?n.message:void 0}function y(e,t){let n=O(e,D(t));if(!p.value.has(n))return;let r=new Map(p.value);r.delete(n),p.value=r}function b(e,t){return y(e,t),x(e,t)}async function x(e,t){let n=O(e,D(t));if(_(e,t)||m.get(n)===t)return;m.set(n,t);let r=new URLSearchParams({path:t.newPath,oldPath:t.oldPath,status:t.status});try{let i=Z(await T(`/api/diff/${e}/file?${r}`));if(!h(e).includes(t))return;f.value=new Map(f.value).set(n,{file:i,for:t}),y(e,t)}catch(r){if(!h(e).includes(t))return;p.value=new Map(p.value).set(n,{message:w(r),for:t})}finally{m.get(n)===t&&m.delete(n)}}function S(){let n=new Set([...e.value.map(e=>O(`staged`,D(e))),...t.value.map(e=>O(`unstaged`,D(e)))]),r=new Map([...f.value].filter(([e])=>n.has(e)));r.size!==f.value.size&&(f.value=r);let i=new Map([...p.value].filter(([e])=>n.has(e)));i.size!==p.value.size&&(p.value=i)}let C=ee(E);async function E(){i.value=!0;try{let[i,a]=await Promise.all([T(`/api/diff/staged/files`),T(`/api/diff/unstaged/files`)]),o=Q(e.value,n,i.map(Z)),c=Q(t.value,r,a.map(Z));e.value=o.files,n=o.signatures,t.value=c.files,r=c.signatures,S(),he([...o.files,...c.files].map(D)),s.value=null}catch(i){a.value||(e.value=[],t.value=[],n=new Map,r=new Map),s.value=w(i)}finally{i.value=!1,a.value=!0}}return{stagedFiles:e,unstagedFiles:t,loading:i,loaded:a,initialLoading:l,error:s,changedPaths:d,hunksOf:g,hunksFresh:_,hunksError:v,clearHunksError:y,ensureHunks:x,retryHunks:b,fetchDiff:C}});function $(e){let{snapshotData:t,...n}=e;return n}var xe=b(`active-review`,()=>{let e=c(null),t=c([]),n=c(!1),r=u(()=>{let e=new Map;for(let n of t.value){let t=e.get(n.filePath);t?t.push(n):e.set(n.filePath,[n])}return e});async function i(){n.value=!0;try{let n=(await T(`/api/reviews`)).filter(e=>e.status===`in_progress`).sort((e,t)=>t.createdAt.localeCompare(e.createdAt));e.value=n[0]??null,t.value=e.value?await T(`/api/reviews/${e.value.id}/comments`):[]}finally{n.value=!1}}function a(n){e.value=$(n),t.value=[]}async function o(t){e.value&&(await x(`/api/reviews/${e.value.id}`,{status:t}),await i())}async function s(n){if(!e.value)throw Error(`No active review`);let r=await S(`/api/reviews/${e.value.id}/comments`,n);return t.value=[...t.value,r],r}async function l(e,n){let r=await x(`/api/comments/${e}`,{content:n});t.value=t.value.map(t=>t.id===e?r:t)}async function d(e){await C(`/api/comments/${e}`),t.value=t.value.filter(t=>t.id!==e)}async function f(e){let n=await x(`/api/comments/${e}/resolve`);t.value=t.value.map(t=>t.id===e?n:t)}async function p(e){let n=await x(`/api/comments/${e}/unresolve`);t.value=t.value.map(t=>t.id===e?n:t)}return{activeReview:e,comments:t,loading:n,commentsByFile:r,refresh:i,setActiveReview:a,setStatus:o,createComment:s,editComment:l,deleteComment:d,resolveComment:f,unresolveComment:p}}),Se=i({__name:`CancelButton`,setup(e){let{t}=y();return(e,r)=>(n(),s(g,d({padding:`2px 8px`},e.$attrs,{dense:``,flat:``,color:`warning`,label:l(t)(`reviews.comments.cancel`)}),null,16,[`label`]))}}),Ce=i({__name:`CreateButton`,setup(e){let{t}=y();return(e,r)=>(n(),s(g,d({padding:`2px 8px`,label:l(t)(`reviews.create.submit`)},e.$attrs,{unelevated:``,dense:``,color:`accent`}),null,16,[`label`]))}}),we=_({name:`QPage`,props:{padding:Boolean,styleFn:Function},setup(e,{slots:t}){let n=f(),i=r(h,p);if(i===p)return console.error(`QPage needs to be a deep child of QLayout`),p;if(r(`_q_pc_`,p)===p)return console.error(`QPage needs to be child of QPageContainer`),p;let o=u(()=>{let t=(i.header.space?i.header.size:0)+(i.footer.space?i.footer.size:0);if(typeof e.styleFn==`function`){let r=i.isContainer.value?i.containerHeight.value:n.screen.height;return e.styleFn(t,r)}return{minHeight:i.isContainer.value?i.containerHeight.value-t+`px`:n.screen.height===0?t===0?`100vh`:`calc(100vh - ${t}px)`:n.screen.height-t+`px`}}),s=u(()=>`q-page${e.padding?` q-layout-padding`:``}`);return()=>a(`main`,{class:s.value,style:o.value},m(t.default))}}),Te=i({__name:`AppPage`,setup(r){function i(e,t){return{height:`${t-e}px`}}return(r,a)=>(n(),s(we,{"style-fn":i},{default:e(()=>[t(r.$slots,`default`)]),_:3}))}});export{$ as a,pe as c,k as d,O as f,xe as i,_e as l,E as m,Ce as n,be as o,D as p,Se as r,ve as s,Te as t,W as u};
|