@tequila99/githuman 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/README.md +8 -2
  2. package/dist/server/errors/git.js +2 -0
  3. package/dist/server/routes/agent.js +8 -2
  4. package/dist/server/routes/git.js +5 -2
  5. package/dist/server/services/agent/agent-session.js +2 -1
  6. package/dist/server/services/agent/context-builder.js +49 -2
  7. package/dist/server/services/agent/file-index.js +7 -4
  8. package/dist/server/services/git.service.js +44 -4
  9. package/dist/server/utils/sse.js +76 -5
  10. package/dist/shared/agents/file-search.js +19 -7
  11. package/dist/shared/agents/mention-paths.js +40 -0
  12. package/dist/shared/agents/schemas.js +13 -4
  13. package/dist/shared/git/schemas.js +4 -1
  14. package/dist/shared/utils/guards.js +3 -0
  15. package/dist/web/assets/{AppPage-D_OHhrKS.js → AppPage-CiRB13sb.js} +2 -2
  16. package/dist/web/assets/CreateReviewFabButton-DTvX9Psc.js +1 -0
  17. package/dist/web/assets/{ErrorNotFound-jc5_L_-4.js → ErrorNotFound-CYOZg8yN.js} +1 -1
  18. package/dist/web/assets/IndexPage-CYFIGWy9.css +1 -0
  19. package/dist/web/assets/IndexPage-hI7bcJ6L.js +1 -0
  20. package/dist/web/assets/MainLayout-DCexR9_Y.css +1 -0
  21. package/dist/web/assets/MainLayout-baVxjyeL.js +11 -0
  22. package/dist/web/assets/PdfPreview-Cb0xawi0.css +1 -0
  23. package/dist/web/assets/PdfPreview-D3HwZ7pH.js +54 -0
  24. package/dist/web/assets/{QBtn-Bgm40omM.js → QBtn-CzrOO1zA.js} +1 -1
  25. package/dist/web/assets/{QBadge-BY-jTQ8w.js → QScrollArea-Cu8zdp0y.js} +1 -1
  26. package/dist/web/assets/QSelect-DQ_RRYIL.js +1 -0
  27. package/dist/web/assets/QSpace-CEuZSBS2.js +13 -0
  28. package/dist/web/assets/ReviewDetailPage-CayB2dtb.js +1 -0
  29. package/dist/web/assets/ReviewDetailPage-CkCilMNW.css +1 -0
  30. package/dist/web/assets/ReviewsPage-DWfEVjWO.js +1 -0
  31. package/dist/web/assets/StatusSwitcher--zNcE2-Y.js +1 -0
  32. package/dist/web/assets/StatusSwitcher-DTD5inU1.css +1 -0
  33. package/dist/web/assets/TerminalView-DvVbWk3f.js +19 -0
  34. package/dist/web/assets/{abnfDiagram-O67JEVCF-4qpB0CGh.js → abnfDiagram-O67JEVCF-C5SYdl8k.js} +1 -1
  35. package/dist/web/assets/agent-store-DX4gIEHa.js +1 -0
  36. package/dist/web/assets/app-info-store-Vy_Pq2yR.js +1 -0
  37. package/dist/web/assets/architecture-7GRP2DOG-Dpxe25D8.js +1 -0
  38. package/dist/web/assets/{architectureDiagram-NJMV4G6O-CEL-_i5O.js → architectureDiagram-NJMV4G6O-Bx8KGjS_.js} +1 -1
  39. package/dist/web/assets/{blockDiagram-BEXU5L5S-bMrUf1GU.js → blockDiagram-BEXU5L5S-B4ybhPir.js} +1 -1
  40. package/dist/web/assets/{c4Diagram-YGBWAQC7-C54mp6dl.js → c4Diagram-YGBWAQC7-D2Fzm9Zx.js} +1 -1
  41. package/dist/web/assets/channel--0tdF_Sb.js +1 -0
  42. package/dist/web/assets/{chunk-3FUC2YCW-BtIughAT.js → chunk-3FUC2YCW-DLRX-HPs.js} +1 -1
  43. package/dist/web/assets/{chunk-5DYCD2WN-BhyMEDuJ.js → chunk-5DYCD2WN-6HcgVbfR.js} +1 -1
  44. package/dist/web/assets/{chunk-742MDFTN-8MczzxE2.js → chunk-742MDFTN-CfTGkhlJ.js} +1 -1
  45. package/dist/web/assets/{chunk-7INBJB4K-BdS9oIIG.js → chunk-7INBJB4K-COfv2qWf.js} +1 -1
  46. package/dist/web/assets/{chunk-7M6MHVWA-BU5_UwaZ.js → chunk-7M6MHVWA-D0FxecF4.js} +5 -5
  47. package/dist/web/assets/{chunk-7PRAP22T-BaAw-gEj.js → chunk-7PRAP22T-DFjSoEy0.js} +1 -1
  48. package/dist/web/assets/{chunk-GTNCS2PH-DNpH8E_x.js → chunk-GTNCS2PH-CGWGXDNO.js} +1 -1
  49. package/dist/web/assets/{chunk-GWA4HPMP-BvG5tXy2.js → chunk-GWA4HPMP-J0EaOPjD.js} +1 -1
  50. package/dist/web/assets/{chunk-MBY4JIJT-B8XJMHG2.js → chunk-MBY4JIJT-PzEUkWiy.js} +1 -1
  51. package/dist/web/assets/{chunk-NETBCI7D-ClCXW1dx.js → chunk-NETBCI7D-DHHOcLF0.js} +1 -1
  52. package/dist/web/assets/{chunk-O7XYJQB3-BNcB0oiZ.js → chunk-O7XYJQB3-BHUId2wW.js} +1 -1
  53. package/dist/web/assets/{chunk-UA2S7LBM-CS5CtIsj.js → chunk-UA2S7LBM-DXQ1DAj6.js} +1 -1
  54. package/dist/web/assets/{chunk-WEXAMYUT-CJaZJWKF.js → chunk-WEXAMYUT-BMiibMha.js} +1 -1
  55. package/dist/web/assets/{chunk-Z7XXMR3K-DP2k1Ci5.js → chunk-Z7XXMR3K-BcgKYeJS.js} +1 -1
  56. package/dist/web/assets/{chunk-ZIGJFQKS-y4KHfdEv.js → chunk-ZIGJFQKS-D6psU74o.js} +1 -1
  57. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-C-kWcloV.js → classDiagram-v2-NBCMYWYE-6IwOSgSE.js} +4 -4
  58. package/dist/web/assets/create-BSmXD9Zr.js +1 -0
  59. package/dist/web/assets/{cynefin-OW5HDTMX-C3AwH_vU.js → cynefin-OW5HDTMX-C77WtKve.js} +1 -1
  60. package/dist/web/assets/{cynefinDiagram-VND7K2PF-DYF_CoB8.js → cynefinDiagram-VND7K2PF-BvIp3Y9w.js} +1 -1
  61. package/dist/web/assets/{dagre-6A5THRUB-DWCEmsd1.js → dagre-6A5THRUB-DN7jrLfY.js} +1 -1
  62. package/dist/web/assets/{diagram-22UHCM2B-oBFhSpao.js → diagram-22UHCM2B-DQUkKx9q.js} +8 -8
  63. package/dist/web/assets/{diagram-3UASUU5V-Cj9rB07y.js → diagram-3UASUU5V-CTzVKsCf.js} +1 -1
  64. package/dist/web/assets/{diagram-ATOU4E4O-D4H9BqUQ.js → diagram-ATOU4E4O--Z3AVUjn.js} +1 -1
  65. package/dist/web/assets/{diagram-CDSNMT55-qLgJBiIs.js → diagram-CDSNMT55-BA-cRZ39.js} +1 -1
  66. package/dist/web/assets/{diagram-MLGK6HIB-Bhhvtx0A.js → diagram-MLGK6HIB-Bx_zLrYg.js} +1 -1
  67. package/dist/web/assets/{diagram-MPIPVDR6-O4wokd54.js → diagram-MPIPVDR6-CWKuh-e-.js} +1 -1
  68. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-BRU7SszO.js → ebnfDiagram-ZINNZB2B-MyQLfQVI.js} +1 -1
  69. package/dist/web/assets/{elk-276RUBZZ-r0X8f7Sv.js → elk-276RUBZZ-DBbqEAnd.js} +1 -1
  70. package/dist/web/assets/{erDiagram-OPXOYQCR-DbgjsGkX.js → erDiagram-OPXOYQCR-CbRo_Rnk.js} +1 -1
  71. package/dist/web/assets/eventmodeling-NTZA5JFV-DMla2cPF.js +1 -0
  72. package/dist/web/assets/flowDiagram-KWPJA3E3-Bas61_mX.js +1 -0
  73. package/dist/web/assets/{ganttDiagram-FUAMR5RP-BwhUglGo.js → ganttDiagram-FUAMR5RP-D1gJBc1W.js} +1 -1
  74. package/dist/web/assets/{gitGraph-4MIJSDKK-DA11BsSo.js → gitGraph-4MIJSDKK-CIzz8UCs.js} +1 -1
  75. package/dist/web/assets/{gitGraphDiagram-X574FWY7-BdG7d-11.js → gitGraphDiagram-X574FWY7-B5-RB5JZ.js} +1 -1
  76. package/dist/web/assets/i18n-B1_G449i.js +1 -0
  77. package/dist/web/assets/index-DEwYKvIG.js +2 -0
  78. package/dist/web/assets/{index-BatRsx0U.css → index-Dma-RXBR.css} +1 -1
  79. package/dist/web/assets/{info-A6RAGUB7-BxzfvGqu.js → info-A6RAGUB7-DF-JCGlS.js} +1 -1
  80. package/dist/web/assets/{infoDiagram-VRGFBTTK-veq817ut.js → infoDiagram-VRGFBTTK-z0Xepdo0.js} +1 -1
  81. package/dist/web/assets/init-app-DAsY3Joz.js +1 -0
  82. package/dist/web/assets/{is-EbmiuVzv.js → is-DssfAlMe.js} +1 -1
  83. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-DMuzkArR.js → ishikawaDiagram-OU5B5YK6-UqXiqAoe.js} +1 -1
  84. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-Cqj0kbKe.js → journeyDiagram-ZHPQQLJL-CPGeWRg-.js} +1 -1
  85. package/dist/web/assets/{kanban-definition-PNTS6WVX-DUvral0v.js → kanban-definition-PNTS6WVX-CMq9WuD5.js} +1 -1
  86. package/dist/web/assets/{line-DcLaUOyJ.js → line-cZB9xcQk.js} +1 -1
  87. package/dist/web/assets/{mermaid-parser.core-CY7nVQ2O.js → mermaid-parser.core-D8h1T47v.js} +3 -3
  88. package/dist/web/assets/{mermaid.core-Cz083qmW.js → mermaid.core-CdpJws-B.js} +7 -7
  89. package/dist/web/assets/{mindmap-definition-NLK3R4M7--Twjhxcv.js → mindmap-definition-NLK3R4M7-B01KHb5Z.js} +1 -1
  90. package/dist/web/assets/{packet-AYTQ26CC-Csf3Pf50.js → packet-AYTQ26CC-CagxQ791.js} +1 -1
  91. package/dist/web/assets/pdf.worker-C2cQdohj.js +48 -0
  92. package/dist/web/assets/{pegDiagram-GJSIUBJH-vVjFUYc4.js → pegDiagram-GJSIUBJH-amhZRgGf.js} +1 -1
  93. package/dist/web/assets/{pie-WAS4IAKB-CyUE71ZQ.js → pie-WAS4IAKB-zv3udP2i.js} +1 -1
  94. package/dist/web/assets/{pieDiagram-5QR66LMP-CV24sdEs.js → pieDiagram-5QR66LMP-CjPzT-fa.js} +1 -1
  95. package/dist/web/assets/{pinia-ri8AYppz.js → pinia-DCsnCHsH.js} +1 -1
  96. package/dist/web/assets/pinia-DWj71cM9.js +1 -0
  97. package/dist/web/assets/{quadrantDiagram-O4NWA36T-GVAUaTqf.js → quadrantDiagram-O4NWA36T-7YpPBn0t.js} +1 -1
  98. package/dist/web/assets/{radar-RG4KPBEZ-D7YGMFYX.js → radar-RG4KPBEZ-DZ-nSYpA.js} +1 -1
  99. package/dist/web/assets/{railroad-74A4TZTK-BYsDf4cg.js → railroad-74A4TZTK-CoylUO-u.js} +1 -1
  100. package/dist/web/assets/railroad-abnf-HS5TGJTU-C20Z1OCq.js +1 -0
  101. package/dist/web/assets/railroad-ebnf-LZEXJU2U-BltGHYDI.js +1 -0
  102. package/dist/web/assets/railroad-peg-WCYAUIDC-BT3QI-zw.js +1 -0
  103. package/dist/web/assets/{railroadDiagram-XR7U4H2S-DOyP7Y6B.js → railroadDiagram-XR7U4H2S-DlHZky0v.js} +1 -1
  104. package/dist/web/assets/{requirementDiagram-PLB6GJNP-C2CJ05_O.js → requirementDiagram-PLB6GJNP-Dn9whLhB.js} +1 -1
  105. package/dist/web/assets/{runtime-core.esm-bundler-CF89Lyp2.js → runtime-core.esm-bundler-BKFI1w28.js} +1 -1
  106. package/dist/web/assets/{safe-storage-BpHrcFXl.js → safe-storage-B3bJArYP.js} +1 -1
  107. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-rYUTxo-7.js → sankeyDiagram-IPEJSGJF-jIf4UAnN.js} +1 -1
  108. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-Dy-NGv9K.js → sequenceDiagram-PO4LG4MO-CJahxeyg.js} +1 -1
  109. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-_uEXf3B4.js → stateDiagram-v2-GCMORJYK-DArbI5q3.js} +2 -2
  110. package/dist/web/assets/{swimlanes-2SLR337P-CcejXyI9.js → swimlanes-2SLR337P-wyJPqm8c.js} +1 -1
  111. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-DgRybibH.js +8 -0
  112. package/dist/web/assets/theme-CFC7Mb_O.js +1 -0
  113. package/dist/web/assets/{timeline-definition-EJHVYXUP-CSry3jW1.js → timeline-definition-EJHVYXUP-Bdh9ma4o.js} +1 -1
  114. package/dist/web/assets/{treeView-Q6P3EWNA-CUCgNMVi.js → treeView-Q6P3EWNA-CEiXTwqS.js} +1 -1
  115. package/dist/web/assets/{treemap-WGGIJYW6-BtG_xZt4.js → treemap-WGGIJYW6-am0aIfU-.js} +1 -1
  116. package/dist/web/assets/use-app-theme-FYzHIigd.js +1 -0
  117. package/dist/web/assets/use-panel-width-e-yXva8i.js +1 -0
  118. package/dist/web/assets/use-server-events-znzHKZZx.js +1 -0
  119. package/dist/web/assets/{use-virtual-scroll-DTEGubei.js → use-virtual-scroll-CIwaJCUj.js} +1 -1
  120. package/dist/web/assets/{usecaseDiagram-POWQR4AR-BY2X6VR2.js → usecaseDiagram-POWQR4AR-r3Qf5Bj-.js} +1 -1
  121. package/dist/web/assets/{vennDiagram-UO4OBE2U-D-khbRsr.js → vennDiagram-UO4OBE2U-eOWNPvLI.js} +1 -1
  122. package/dist/web/assets/{vue-i18n.runtime-BTqPc4vG.js → vue-i18n.runtime-BpRrzZrT.js} +2 -2
  123. package/dist/web/assets/{wardley-WFR3VGLG-BwwTtxgX.js → wardley-WFR3VGLG-BdipY77V.js} +1 -1
  124. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-N4eN_Mx8.js → wardleyDiagram-VNRHLVJA-sFpl0u9C.js} +1 -1
  125. package/dist/web/assets/{xychartDiagram-PMCCYNJV-Bp3do5lv.js → xychartDiagram-PMCCYNJV-CtLqW--F.js} +1 -1
  126. package/dist/web/index.html +6 -6
  127. package/dist/web/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  128. package/dist/web/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  129. package/dist/web/pdfjs/cmaps/78-H.bcmap +0 -0
  130. package/dist/web/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  131. package/dist/web/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  132. package/dist/web/pdfjs/cmaps/78-V.bcmap +0 -0
  133. package/dist/web/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  134. package/dist/web/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  135. package/dist/web/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  136. package/dist/web/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  137. package/dist/web/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  138. package/dist/web/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  139. package/dist/web/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  140. package/dist/web/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  141. package/dist/web/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  142. package/dist/web/pdfjs/cmaps/Add-H.bcmap +0 -0
  143. package/dist/web/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  144. package/dist/web/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  145. package/dist/web/pdfjs/cmaps/Add-V.bcmap +0 -0
  146. package/dist/web/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  147. package/dist/web/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  148. package/dist/web/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  149. package/dist/web/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  150. package/dist/web/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  151. package/dist/web/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  152. package/dist/web/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  153. package/dist/web/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  154. package/dist/web/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  155. package/dist/web/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  156. package/dist/web/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  157. package/dist/web/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  158. package/dist/web/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  159. package/dist/web/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  160. package/dist/web/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  161. package/dist/web/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  162. package/dist/web/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  163. package/dist/web/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  164. package/dist/web/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  165. package/dist/web/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  166. package/dist/web/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  167. package/dist/web/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  168. package/dist/web/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  169. package/dist/web/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  170. package/dist/web/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  171. package/dist/web/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  172. package/dist/web/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  173. package/dist/web/pdfjs/cmaps/B5-H.bcmap +0 -0
  174. package/dist/web/pdfjs/cmaps/B5-V.bcmap +0 -0
  175. package/dist/web/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  176. package/dist/web/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  177. package/dist/web/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  178. package/dist/web/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  179. package/dist/web/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  180. package/dist/web/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  181. package/dist/web/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  182. package/dist/web/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  183. package/dist/web/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  184. package/dist/web/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  185. package/dist/web/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  186. package/dist/web/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  187. package/dist/web/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  188. package/dist/web/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  189. package/dist/web/pdfjs/cmaps/EUC-H.bcmap +0 -0
  190. package/dist/web/pdfjs/cmaps/EUC-V.bcmap +0 -0
  191. package/dist/web/pdfjs/cmaps/Ext-H.bcmap +0 -0
  192. package/dist/web/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  193. package/dist/web/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  194. package/dist/web/pdfjs/cmaps/Ext-V.bcmap +0 -0
  195. package/dist/web/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  196. package/dist/web/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  197. package/dist/web/pdfjs/cmaps/GB-H.bcmap +4 -0
  198. package/dist/web/pdfjs/cmaps/GB-V.bcmap +0 -0
  199. package/dist/web/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  200. package/dist/web/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  201. package/dist/web/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  202. package/dist/web/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  203. package/dist/web/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  204. package/dist/web/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  205. package/dist/web/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  206. package/dist/web/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  207. package/dist/web/pdfjs/cmaps/GBT-H.bcmap +0 -0
  208. package/dist/web/pdfjs/cmaps/GBT-V.bcmap +0 -0
  209. package/dist/web/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  210. package/dist/web/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  211. package/dist/web/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  212. package/dist/web/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  213. package/dist/web/pdfjs/cmaps/H.bcmap +0 -0
  214. package/dist/web/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  215. package/dist/web/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  216. package/dist/web/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  217. package/dist/web/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  218. package/dist/web/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  219. package/dist/web/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  220. package/dist/web/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  221. package/dist/web/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  222. package/dist/web/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  223. package/dist/web/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  224. package/dist/web/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  225. package/dist/web/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  226. package/dist/web/pdfjs/cmaps/Hankaku.bcmap +0 -0
  227. package/dist/web/pdfjs/cmaps/Hiragana.bcmap +0 -0
  228. package/dist/web/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  229. package/dist/web/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  230. package/dist/web/pdfjs/cmaps/KSC-H.bcmap +0 -0
  231. package/dist/web/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  232. package/dist/web/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  233. package/dist/web/pdfjs/cmaps/KSC-V.bcmap +0 -0
  234. package/dist/web/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  235. package/dist/web/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  236. package/dist/web/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  237. package/dist/web/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  238. package/dist/web/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  239. package/dist/web/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  240. package/dist/web/pdfjs/cmaps/Katakana.bcmap +0 -0
  241. package/dist/web/pdfjs/cmaps/LICENSE +36 -0
  242. package/dist/web/pdfjs/cmaps/NWP-H.bcmap +0 -0
  243. package/dist/web/pdfjs/cmaps/NWP-V.bcmap +0 -0
  244. package/dist/web/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  245. package/dist/web/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  246. package/dist/web/pdfjs/cmaps/Roman.bcmap +0 -0
  247. package/dist/web/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  248. package/dist/web/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  249. package/dist/web/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  250. package/dist/web/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  251. package/dist/web/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  252. package/dist/web/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  253. package/dist/web/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  254. package/dist/web/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  255. package/dist/web/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  256. package/dist/web/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  257. package/dist/web/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  258. package/dist/web/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  259. package/dist/web/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  260. package/dist/web/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  261. package/dist/web/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  262. package/dist/web/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  263. package/dist/web/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  264. package/dist/web/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  265. package/dist/web/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  266. package/dist/web/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  267. package/dist/web/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  268. package/dist/web/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  269. package/dist/web/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  270. package/dist/web/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  271. package/dist/web/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  272. package/dist/web/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  273. package/dist/web/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  274. package/dist/web/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  275. package/dist/web/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  276. package/dist/web/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  277. package/dist/web/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  278. package/dist/web/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  279. package/dist/web/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  280. package/dist/web/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  281. package/dist/web/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  282. package/dist/web/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  283. package/dist/web/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  284. package/dist/web/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  285. package/dist/web/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  286. package/dist/web/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  287. package/dist/web/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  288. package/dist/web/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  289. package/dist/web/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  290. package/dist/web/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  291. package/dist/web/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  292. package/dist/web/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  293. package/dist/web/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  294. package/dist/web/pdfjs/cmaps/V.bcmap +0 -0
  295. package/dist/web/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  296. package/dist/web/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  297. package/dist/web/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  298. package/dist/web/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  299. package/dist/web/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  300. package/dist/web/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  301. package/dist/web/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  302. package/dist/web/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  303. package/dist/web/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  304. package/dist/web/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  305. package/dist/web/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  306. package/dist/web/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  307. package/dist/web/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
  308. package/dist/web/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  309. package/dist/web/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  310. package/dist/web/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  311. package/dist/web/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  312. package/dist/web/pdfjs/wasm/LICENSE_JBIG2 +196 -0
  313. package/dist/web/pdfjs/wasm/LICENSE_OPENJPEG +39 -0
  314. package/dist/web/pdfjs/wasm/LICENSE_PDFJS_JBIG2 +13 -0
  315. package/dist/web/pdfjs/wasm/LICENSE_PDFJS_OPENJPEG +22 -0
  316. package/dist/web/pdfjs/wasm/LICENSE_PDFJS_QCMS +19 -0
  317. package/dist/web/pdfjs/wasm/LICENSE_QCMS +21 -0
  318. package/dist/web/pdfjs/wasm/jbig2.wasm +0 -0
  319. package/dist/web/pdfjs/wasm/jbig2_nowasm_fallback.js +15 -0
  320. package/dist/web/pdfjs/wasm/openjpeg.wasm +0 -0
  321. package/dist/web/pdfjs/wasm/openjpeg_nowasm_fallback.js +17 -0
  322. package/dist/web/pdfjs/wasm/qcms_bg.wasm +0 -0
  323. package/dist/web/pdfjs/wasm/quickjs-eval.js +16 -0
  324. package/dist/web/pdfjs/wasm/quickjs-eval.wasm +0 -0
  325. package/package.json +3 -1
  326. package/dist/web/assets/CreateReviewFabButton-B737aIvn.js +0 -1
  327. package/dist/web/assets/IndexPage-DzlFTw_b.js +0 -1
  328. package/dist/web/assets/IndexPage-u_qqIPRL.css +0 -1
  329. package/dist/web/assets/MainLayout-DaSyo22r.js +0 -8
  330. package/dist/web/assets/MainLayout-DoniW026.css +0 -1
  331. package/dist/web/assets/QSelect-713AWDd_.js +0 -1
  332. package/dist/web/assets/QSpace-BLu5AyZv.css +0 -1
  333. package/dist/web/assets/QSpace-BVBU-0oC.js +0 -17
  334. package/dist/web/assets/ReviewDetailPage-CLM6aU4u.js +0 -1
  335. package/dist/web/assets/ReviewDetailPage-CP6YqXPT.css +0 -1
  336. package/dist/web/assets/ReviewsPage-bllnaoOS.js +0 -1
  337. package/dist/web/assets/StatusSwitcher-BZ4FYVnY.js +0 -2
  338. package/dist/web/assets/StatusSwitcher-BxRuEHHQ.css +0 -1
  339. package/dist/web/assets/TerminalView-Ci9CNTyY.js +0 -19
  340. package/dist/web/assets/agent-store-DIma0R4U.js +0 -1
  341. package/dist/web/assets/app-info-store-BzsJOxVc.js +0 -1
  342. package/dist/web/assets/architecture-7GRP2DOG-DG6nf_hE.js +0 -1
  343. package/dist/web/assets/channel-CS4rbjhf.js +0 -1
  344. package/dist/web/assets/create-CSUVwdx4.js +0 -1
  345. package/dist/web/assets/eventmodeling-NTZA5JFV-1Q8-FsiO.js +0 -1
  346. package/dist/web/assets/export-file-Di_2jvjP.js +0 -1
  347. package/dist/web/assets/flowDiagram-KWPJA3E3-BbwsRPsv.js +0 -1
  348. package/dist/web/assets/i18n-D1K2AGeW.js +0 -1
  349. package/dist/web/assets/index-DuCIKkvf.js +0 -2
  350. package/dist/web/assets/init-app-DKRVN8HV.js +0 -1
  351. package/dist/web/assets/pinia-UjhgYLzw.js +0 -1
  352. package/dist/web/assets/railroad-abnf-HS5TGJTU-Bg7f5Sbu.js +0 -1
  353. package/dist/web/assets/railroad-ebnf-LZEXJU2U-ufUodNib.js +0 -1
  354. package/dist/web/assets/railroad-peg-WCYAUIDC-YvUtEf_g.js +0 -1
  355. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-I9_cJ2VX.js +0 -8
  356. package/dist/web/assets/theme-Dv0yhgRD.js +0 -1
  357. package/dist/web/assets/use-app-theme-CSRcIN0e.js +0 -1
  358. package/dist/web/assets/use-panel-width-DNg6NE2M.js +0 -1
  359. 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
  отдельного чата можно включить автоподтверждение (кнопка-щит) — агент
@@ -0,0 +1,2 @@
1
+ import createError from '@fastify/error';
2
+ export const GitFileNotFoundError = createError('GHT_GIT_FILE_NOT_FOUND', '%s', 404);
@@ -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
- files: await fileIndex.search(request.query.q ?? '', request.query.limit ?? DEFAULT_FILE_SEARCH_LIMIT)
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
- const MAX_BUFFERED_EVENTS = 5_000;
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 { rankFiles } from "../../../shared/agents/file-search.js";
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 = rankFiles(await files(), query);
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
  }
@@ -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
- * Sends one SSE message and never fails. A client can leave at any time, and
3
- * `send` then rejects. Nothing awaits that promise, so Node would end the
4
- * process on the unhandled rejection.
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
- sse.send(message).catch(() => { });
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
- const base = lower.slice(lower.lastIndexOf('/') + 1);
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 `files` by how well they match `query`: file name first (exact,
31
- * prefix, substring), then anywhere in the path, then as scattered letters.
32
- * Ties go to the shorter path. An empty query matches everything.
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 rankFiles(files, query) {
45
+ export function rankPaths(paths, query) {
35
46
  const needle = query.trim().toLowerCase();
36
47
  const scored = [];
37
- for (const path of files) {
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
- files: Type.Array(Type.String(), {
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(), {
@@ -2,3 +2,6 @@
2
2
  export function isRecord(value) {
3
3
  return typeof value === 'object' && value !== null && !Array.isArray(value);
4
4
  }
5
+ export function isFiniteNumber(value) {
6
+ return typeof value === 'number' && Number.isFinite(value);
7
+ }
@@ -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,at as a,b as o,ft as s,l as c,s as l,st as u,w as d}from"./runtime-core.esm-bundler-CF89Lyp2.js";import{D as f,O as p,_ as m,j as h,t as g}from"./QBtn-Bgm40omM.js";import{t as _}from"./create-CSUVwdx4.js";import{F as v}from"./index-DuCIKkvf.js";import{n as y}from"./vue-i18n.runtime-BTqPc4vG.js";import{n as b}from"./pinia-ri8AYppz.js";import{d as x,f as S,l as C,o as ee,s as w,u as T}from"./use-server-events-CYiRauy1.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(`
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-DEwYKvIG.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=a([]),t=a([]),n=new Map,r=new Map,i=a(!1),o=a(!1),s=a(null),c=l(()=>i.value&&!o.value),d=l(()=>[...e.value,...t.value].map(e=>e.newPath||e.oldPath)),f=u(new Map),p=u(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){o.value||(e.value=[],t.value=[],n=new Map,r=new Map),s.value=w(i)}finally{i.value=!1,o.value=!0}}return{stagedFiles:e,unstagedFiles:t,loading:i,loaded:o,initialLoading:c,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=a(null),t=a([]),n=a(!1),r=l(()=>{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 o(n){e.value=$(n),t.value=[]}async function s(t){e.value&&(await x(`/api/reviews/${e.value.id}`,{status:t}),await i())}async function c(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 u(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:o,setStatus:s,createComment:c,editComment:u,deleteComment:d,resolveComment:f,unresolveComment:p}}),Se=i({__name:`CancelButton`,setup(e){let{t}=y();return(e,r)=>(n(),c(g,d({padding:`2px 8px`},e.$attrs,{dense:``,flat:``,color:`warning`,label:s(t)(`reviews.comments.cancel`)}),null,16,[`label`]))}}),Ce=i({__name:`CreateButton`,setup(e){let{t}=y();return(e,r)=>(n(),c(g,d({padding:`2px 8px`,label:s(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 a=l(()=>{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=l(()=>`q-page${e.padding?` q-layout-padding`:``}`);return()=>o(`main`,{class:s.value,style:a.value},m(t.default))}}),Te=i({__name:`AppPage`,setup(r){function i(e,t){return{height:`${t-e}px`}}return(r,a)=>(n(),c(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};
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};
@@ -0,0 +1 @@
1
+ import{C as e,F as t,J as n,K as r,P as i,S as a,U as o,Y as s,_ as c,b as l,c as u,ct as d,d as f,h as p,kt as m,l as h,ot as g,pt as _,r as v,s as y,v as b,w as x}from"./runtime-core.esm-bundler-BKFI1w28.js";import{D as S,H as C,O as w,_ as T,d as E,h as D,j as O,k,t as A}from"./QBtn-CzrOO1zA.js";import{t as j}from"./create-BSmXD9Zr.js";import{_ as M,ct as N,f as P,m as F,n as I,ot as L,p as R,q as ee,st as te}from"./index-DEwYKvIG.js";import{n as ne}from"./vue-i18n.runtime-BpRrzZrT.js";import{n as z,r as B}from"./pinia-DCsnCHsH.js";import{f as V,s as H,u as U}from"./use-server-events-znzHKZZx.js";import{t as W}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{a as G,o as K,r as q,u as J}from"./QScrollArea-Cu8zdp0y.js";import{a as Y,i as X,n as Z,o as re,r as ie}from"./AppPage-CiRB13sb.js";var ae=c({__name:`SearchInput`,props:{modelValue:{},modelModifiers:{}},emits:[`update:modelValue`],setup(e){let t=o(e,`modelValue`);return(e,r)=>(i(),h(I,x({modelValue:t.value,"onUpdate:modelValue":r[0]||=e=>t.value=e},e.$attrs,{dense:``,outlined:``,clearable:``}),{prepend:n(()=>[p(E,{name:`search`,size:`xs`})]),_:1},16,[`modelValue`]))}}),oe=[`top`,`right`,`bottom`,`left`],Q={type:{type:String,default:`a`},outline:Boolean,push:Boolean,flat:Boolean,unelevated:Boolean,color:String,textColor:String,glossy:Boolean,square:Boolean,padding:String,label:{type:[String,Number],default:``},labelPosition:{type:String,default:`right`,validator:e=>oe.includes(e)},externalLabel:Boolean,hideLabel:{type:Boolean},labelClass:[Array,String,Object],labelStyle:[Array,String,Object],disable:Boolean,tabindex:[Number,String]},se=[`label`],ce=Object.keys(Q).filter(e=>!se.includes(e)&&A.props[e]!==void 0);function le(e){let t={};for(let n of ce)t[n]=e[n];return t}function ue(e,t){return{formClass:y(()=>`q-fab--form-${e.square?`square`:`rounded`}`),stacked:y(()=>!e.externalLabel&&[`top`,`bottom`].includes(e.labelPosition)),labelProps:y(()=>{if(e.externalLabel){let n=e.hideLabel===null?!t.value:e.hideLabel;return{action:`push`,data:{class:[e.labelClass,`q-fab__label q-tooltip--style q-fab__label--external q-fab__label--external-${e.labelPosition}`+(n?` q-fab__label--external-hidden`:``)],style:e.labelStyle}}}return{action:[`left`,`top`].includes(e.labelPosition)?`unshift`:`push`,data:{class:[e.labelClass,`q-fab__label q-fab__label--internal q-fab__label--internal-${e.labelPosition}`+(e.hideLabel?` q-fab__label--internal-hidden`:``)],style:e.labelStyle}}})}}var de=[`up`,`right`,`down`,`left`],fe=[`left`,`center`,`right`],pe=180,me=j({name:`QFab`,props:{...Q,...N,icon:String,activeIcon:String,hideIcon:Boolean,hideLabel:{...Q.hideLabel,default:null},direction:{type:String,default:`right`,validator:e=>de.includes(e)},...K,persistent:Boolean,stagger:{type:Number,default:40},verticalActionsAlign:{type:String,default:`center`,validator:e=>fe.includes(e)}},emits:te,setup(e,{slots:n}){let i=d(null),a=g(e.modelValue===!0),o=ee(),s=S(),{formClass:c,stacked:u,labelProps:f}=ue(e,a),p=y(()=>!e.persistent),{show:m,hide:h,toggle:_}=L({showing:a,hideOnRouteChange:p}),v=0,{clearHoverTimer:b,hoverShow:x,hoverHide:C}=G({props:e,canShow:()=>!a.value,show:e=>{v=Date.now(),m(e)},canHide:()=>a.value,hide:h});r(a,b);function w(e){a.value&&Date.now()-v<pe||_(e)}let O=y(()=>({opened:a.value})),j=y(()=>`q-fab z-fab row inline justify-center q-fab--align-${e.verticalActionsAlign} ${c.value}`+(a.value?` q-fab--opened`:` q-fab--closed`)),M=y(()=>`q-fab__actions flex no-wrap inline q-fab__actions--${e.direction} q-fab__actions--${a.value?`opened`:`closed`}`),N=y(()=>e.hover?{onPointerenter:x,onPointerleave:C}:{}),P=y(()=>{let t={id:o.value,style:`--q-fab-stagger: ${e.stagger}ms`};return a.value||(t[`aria-hidden`]=`true`),t}),F=y(()=>`q-fab__icon-holder q-fab__icon-holder--${a.value?`opened`:`closed`}`);function I(t,r){let i=n[t],a=`q-fab__${t} absolute-full`;return i===void 0?l(E,{class:a,name:e[r]||s.iconSet.fab[r]}):l(`div`,{class:a},i(O.value))}function R(){let t=[];return e.hideIcon||t.push(l(`div`,{class:F.value},[I(`icon`,`icon`),I(`active-icon`,`activeIcon`)])),(e.label!==``||n.label!==void 0)&&t[f.value.action](l(`div`,f.value.data,n.label===void 0?[e.label]:n.label(O.value))),D(n.tooltip,t)}return t(k,{showing:a,onChildClick(e){h(e),e?.qAvoidFocus!==!0&&i.value?.$el.focus()}}),()=>l(`div`,{class:j.value,...N.value},[l(A,{ref:i,class:c.value,...le(e),noWrap:!0,stack:u.value,noCaps:!0,fab:!0,"aria-expanded":a.value?`true`:`false`,"aria-controls":o.value,onClick:w},R),l(`div`,{class:M.value,...P.value},T(n.default))])}}),he={position:{type:String,default:`bottom-right`,validator:e=>[`top-right`,`top-left`,`bottom-right`,`bottom-left`,`top`,`right`,`bottom`,`left`].includes(e)},offset:{type:Array,validator:e=>e.length===2},expand:Boolean};function ge(){let{props:e}=b(),t=S(),n=a(O,w);if(n===w)return console.error(`QPageSticky needs to be child of QLayout`),w;let r=y(()=>{let t=e.position;return{top:t.includes(`top`),right:t.includes(`right`),bottom:t.includes(`bottom`),left:t.includes(`left`),vertical:t===`top`||t===`bottom`,horizontal:t===`left`||t===`right`}}),i=y(()=>n.header.offset),o=y(()=>n.right.offset),s=y(()=>n.footer.offset),c=y(()=>n.left.offset),u=y(()=>{let n=0,a=0,l=r.value,u=t.lang.rtl?-1:1;l.top&&i.value!==0?a=`${i.value}px`:l.bottom&&s.value!==0&&(a=`${-s.value}px`),l.left&&c.value!==0?n=`${u*c.value}px`:l.right&&o.value!==0&&(n=`${-u*o.value}px`);let d={transform:`translate(${n}, ${a})`};return e.offset&&(d.margin=`${e.offset[1]}px ${e.offset[0]}px`),l.vertical?(c.value!==0&&(d[t.lang.rtl?`right`:`left`]=`${c.value}px`),o.value!==0&&(d[t.lang.rtl?`left`:`right`]=`${o.value}px`)):l.horizontal&&(i.value!==0&&(d.top=`${i.value}px`),s.value!==0&&(d.bottom=`${s.value}px`)),d}),d=y(()=>`q-page-sticky row flex-center fixed-${e.position} q-page-sticky--${e.expand?`expand`:`shrink`}`);function f(t){let n=T(t.default);return l(`div`,{class:d.value,style:u.value},e.expand?n:[l(`div`,n)])}return{$layout:n,getStickyContent:f}}var _e=j({name:`QPageSticky`,props:he,setup(e,{slots:t}){let{getStickyContent:n}=ge();return()=>n(t)}});function ve(e){let t=new URLSearchParams;e.search&&t.set(`search`,e.search),e.createdFrom&&t.set(`createdFrom`,e.createdFrom),e.createdTo&&t.set(`createdTo`,e.createdTo),e.files&&e.files.length>0&&t.set(`files`,e.files.join(`,`));let n=t.toString();return n?`?${n}`:``}var $=z(`reviews`,()=>{let e=g([]),t=g(!1),n=g(null);async function r(r={}){t.value=!0,n.value=null;try{e.value=await U(`/api/reviews${ve(r)}`)}catch(t){e.value=[],n.value=H(t)}finally{t.value=!1}}async function i(t){let n=await V(`/api/reviews`,t);return e.value=[Y(n),...e.value],n}return{reviews:e,loading:t,error:n,fetchReviews:r,createReview:i}}),ye={class:`text-h6`},be=W(c({__name:`ReviewCreateDialog`,props:{modelValue:{type:Boolean,required:!0},modelModifiers:{}},emits:e([`created`,`hide`],[`update:modelValue`]),setup(e,{emit:t}){let r=o(e,`modelValue`),a=t,{t:c}=ne(),l=$(),d=g(``),f=g(!1),v=g(null);function y(){d.value=``,f.value=!1,v.value=null}async function b(){f.value=!0,v.value=null;try{let e=d.value.trim(),t=await l.createReview(e?{name:e}:{});r.value=!1,y(),a(`created`,t)}catch(e){v.value=H(e)}finally{f.value=!1}}function x(){y(),a(`hide`)}return(e,t)=>(i(),h(M,{modelValue:r.value,"onUpdate:modelValue":t[1]||=e=>r.value=e,onHide:x},{default:n(()=>[p(F,{class:`review-create-dialog`},{default:n(()=>[p(R,null,{default:n(()=>[u(`div`,ye,m(_(c)(`reviews.create.title`)),1)]),_:1}),p(R,{class:`q-gutter-y-md`},{default:n(()=>[p(I,{modelValue:d.value,"onUpdate:modelValue":t[0]||=e=>d.value=e,dense:``,outlined:``,label:_(c)(`reviews.create.nameLabel`),hint:_(c)(`reviews.create.nameHint`),error:!!v.value,"error-message":v.value??void 0,onKeyup:C(b,[`enter`])},null,8,[`modelValue`,`label`,`hint`,`error`,`error-message`])]),_:1}),p(P,{align:`right`},{default:n(()=>[s(p(ie,null,null,512),[[q]]),p(Z,{loading:f.value,onClick:b},null,8,[`loading`])]),_:1})]),_:1})]),_:1},8,[`modelValue`]))}}),[[`__scopeId`,`data-v-095646d6`]]),xe=c({__name:`CreateReviewFabButton`,emits:[`created`],setup(e,{emit:t}){let r=t,a=X(),o=re(),{activeReview:c}=B(a),{changedPaths:l}=B(o),u=g(!1),d=g(!1),m=g([18,18]),h=g(!1),_=y(()=>l.value.length===0||c.value!==null);function b(e){h.value=e.isFirst!==!0&&e.isFinal!==!0,m.value=[m.value[0]-(e.delta?.x??0),m.value[1]-(e.delta?.y??0)]}function x(e){a.setActiveReview(e),r(`created`,e)}return(e,t)=>(i(),f(v,null,[p(_e,{position:`bottom-right`,offset:m.value},{default:n(()=>[s(p(me,{modelValue:d.value,"onUpdate:modelValue":t[0]||=e=>d.value=e,icon:`add`,color:`accent`,disable:_.value||h.value,onClick:t[1]||=e=>u.value=!0},null,8,[`modelValue`,`disable`]),[[J,b,void 0,{prevent:!0,mouse:!0}]])]),_:1},8,[`offset`]),p(be,{modelValue:u.value,"onUpdate:modelValue":t[2]||=e=>u.value=e,onCreated:x,onHide:t[3]||=e=>d.value=!1},null,8,[`modelValue`])],64))}});export{$ as n,ae as r,xe as t};
@@ -1 +1 @@
1
- import{P as e,c as t,d as n,h as r}from"./runtime-core.esm-bundler-CF89Lyp2.js";import{t as i}from"./QBtn-Bgm40omM.js";import{t as a}from"./_plugin-vue_export-helper-BDNMzG2s.js";var o={},s={class:`fullscreen bg-blue text-white text-center q-pa-md flex flex-center`};function c(a,o){return e(),n(`div`,s,[t(`div`,null,[o[0]||=t(`div`,{style:{"font-size":`30vh`}},`404`,-1),o[1]||=t(`div`,{class:`text-h2`,style:{opacity:`0.4`}},`Oops. Nothing here...`,-1),r(i,{class:`q-mt-xl`,color:`white`,"text-color":`blue`,unelevated:``,to:`/`,label:`Go Home`,"no-caps":``})])])}var l=a(o,[[`render`,c]]);export{l as default};
1
+ import{P as e,c as t,d as n,h as r}from"./runtime-core.esm-bundler-BKFI1w28.js";import{t as i}from"./QBtn-CzrOO1zA.js";import{t as a}from"./_plugin-vue_export-helper-BDNMzG2s.js";var o={},s={class:`fullscreen bg-blue text-white text-center q-pa-md flex flex-center`};function c(a,o){return e(),n(`div`,s,[t(`div`,null,[o[0]||=t(`div`,{style:{"font-size":`30vh`}},`404`,-1),o[1]||=t(`div`,{class:`text-h2`,style:{opacity:`0.4`}},`Oops. Nothing here...`,-1),r(i,{class:`q-mt-xl`,color:`white`,"text-color":`blue`,unelevated:``,to:`/`,label:`Go Home`,"no-caps":``})])])}var l=a(o,[[`render`,c]]);export{l as default};