@zythum02/fello-server 0.1.46 → 0.1.49

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 (218) hide show
  1. package/README.md +11 -2
  2. package/out/renderer/assets/{_baseUniq-JI50qq3v.js → _baseUniq-jsNn2Q0s.js} +1 -1
  3. package/out/renderer/assets/_baseUniq-jsNn2Q0s.js.br +0 -0
  4. package/out/renderer/assets/_baseUniq-jsNn2Q0s.js.gz +0 -0
  5. package/out/renderer/assets/{arc-D82BffDI.js → arc-CZMdjunT.js} +1 -1
  6. package/out/renderer/assets/arc-CZMdjunT.js.br +0 -0
  7. package/out/renderer/assets/arc-CZMdjunT.js.gz +0 -0
  8. package/out/renderer/assets/{architectureDiagram-Q4EWVU46-BBRMDHvv.js → architectureDiagram-Q4EWVU46-BNFtPc1v.js} +5 -5
  9. package/out/renderer/assets/architectureDiagram-Q4EWVU46-BNFtPc1v.js.br +0 -0
  10. package/out/renderer/assets/architectureDiagram-Q4EWVU46-BNFtPc1v.js.gz +0 -0
  11. package/out/renderer/assets/{blockDiagram-DXYQGD6D-CiCuaiyL.js → blockDiagram-DXYQGD6D-CPK2QuaJ.js} +6 -6
  12. package/out/renderer/assets/blockDiagram-DXYQGD6D-CPK2QuaJ.js.br +0 -0
  13. package/out/renderer/assets/blockDiagram-DXYQGD6D-CPK2QuaJ.js.gz +0 -0
  14. package/out/renderer/assets/{c4Diagram-AHTNJAMY-D9PM_R8p.js → c4Diagram-AHTNJAMY-DLQf0xBh.js} +2 -2
  15. package/out/renderer/assets/c4Diagram-AHTNJAMY-DLQf0xBh.js.br +0 -0
  16. package/out/renderer/assets/c4Diagram-AHTNJAMY-DLQf0xBh.js.gz +0 -0
  17. package/out/renderer/assets/{channel-CklIgqOK.js → channel-sFWrTS52.js} +1 -1
  18. package/out/renderer/assets/{chunk-4BX2VUAB-DK0KQU1M.js → chunk-4BX2VUAB-CUoBhtu2.js} +1 -1
  19. package/out/renderer/assets/{chunk-4TB4RGXK-CxHdBbdg.js → chunk-4TB4RGXK-CRjlV65P.js} +5 -5
  20. package/out/renderer/assets/chunk-4TB4RGXK-CRjlV65P.js.br +0 -0
  21. package/out/renderer/assets/chunk-4TB4RGXK-CRjlV65P.js.gz +0 -0
  22. package/out/renderer/assets/{chunk-55IACEB6-ykIH_AN3.js → chunk-55IACEB6-zrgWErN1.js} +1 -1
  23. package/out/renderer/assets/{chunk-EDXVE4YY-DUOS0pBH.js → chunk-EDXVE4YY-B5b9dJFI.js} +1 -1
  24. package/out/renderer/assets/chunk-EDXVE4YY-B5b9dJFI.js.br +0 -0
  25. package/out/renderer/assets/chunk-EDXVE4YY-B5b9dJFI.js.gz +0 -0
  26. package/out/renderer/assets/{chunk-FMBD7UC4-Bm3BHCuh.js → chunk-FMBD7UC4-Bb0FhBnd.js} +1 -1
  27. package/out/renderer/assets/{chunk-OYMX7WX6-DH9JMSMI.js → chunk-OYMX7WX6-CkUp0SL9.js} +3 -3
  28. package/out/renderer/assets/chunk-OYMX7WX6-CkUp0SL9.js.br +0 -0
  29. package/out/renderer/assets/chunk-OYMX7WX6-CkUp0SL9.js.gz +0 -0
  30. package/out/renderer/assets/{chunk-QZHKN3VN-LffrA1jF.js → chunk-QZHKN3VN-Bqt7zsAR.js} +1 -1
  31. package/out/renderer/assets/{chunk-YZCP3GAM-B1pm_POM.js → chunk-YZCP3GAM-Crg82fz2.js} +1 -1
  32. package/out/renderer/assets/chunk-YZCP3GAM-Crg82fz2.js.br +0 -0
  33. package/out/renderer/assets/chunk-YZCP3GAM-Crg82fz2.js.gz +0 -0
  34. package/out/renderer/assets/{classDiagram-6PBFFD2Q-O6uMquiH.js → classDiagram-6PBFFD2Q-BInpfZnW.js} +6 -6
  35. package/out/renderer/assets/{classDiagram-v2-HSJHXN6E-O6uMquiH.js → classDiagram-v2-HSJHXN6E-BInpfZnW.js} +6 -6
  36. package/out/renderer/assets/{clone-BhlnPWG5.js → clone-Brsdp_jq.js} +1 -1
  37. package/out/renderer/assets/{cose-bilkent-S5V4N54A-ljZi9cz-.js → cose-bilkent-S5V4N54A-CH_2zOJR.js} +1 -1
  38. package/out/renderer/assets/cose-bilkent-S5V4N54A-CH_2zOJR.js.br +0 -0
  39. package/out/renderer/assets/cose-bilkent-S5V4N54A-CH_2zOJR.js.gz +0 -0
  40. package/out/renderer/assets/{dagre-KV5264BT-DqnNoP69.js → dagre-KV5264BT-H1wB7v-Q.js} +6 -6
  41. package/out/renderer/assets/dagre-KV5264BT-H1wB7v-Q.js.br +0 -0
  42. package/out/renderer/assets/dagre-KV5264BT-H1wB7v-Q.js.gz +0 -0
  43. package/out/renderer/assets/{diagram-5BDNPKRD-pBYJseHI.js → diagram-5BDNPKRD-D9VV_-Xi.js} +6 -6
  44. package/out/renderer/assets/diagram-5BDNPKRD-D9VV_-Xi.js.br +0 -0
  45. package/out/renderer/assets/diagram-5BDNPKRD-D9VV_-Xi.js.gz +0 -0
  46. package/out/renderer/assets/{diagram-G4DWMVQ6-IPm9zWeG.js → diagram-G4DWMVQ6-CfRglPBg.js} +6 -6
  47. package/out/renderer/assets/diagram-G4DWMVQ6-CfRglPBg.js.br +0 -0
  48. package/out/renderer/assets/diagram-G4DWMVQ6-CfRglPBg.js.gz +0 -0
  49. package/out/renderer/assets/{diagram-MMDJMWI5-DSH58P_m.js → diagram-MMDJMWI5-BnwRyNpR.js} +5 -5
  50. package/out/renderer/assets/diagram-MMDJMWI5-BnwRyNpR.js.br +0 -0
  51. package/out/renderer/assets/diagram-MMDJMWI5-BnwRyNpR.js.gz +0 -0
  52. package/out/renderer/assets/{diagram-TYMM5635-Czl-GGCp.js → diagram-TYMM5635-BKn_5Ga7.js} +5 -5
  53. package/out/renderer/assets/diagram-TYMM5635-BKn_5Ga7.js.br +0 -0
  54. package/out/renderer/assets/diagram-TYMM5635-BKn_5Ga7.js.gz +0 -0
  55. package/out/renderer/assets/{erDiagram-SMLLAGMA-BENPNKae.js → erDiagram-SMLLAGMA-B35CLzqQ.js} +4 -4
  56. package/out/renderer/assets/erDiagram-SMLLAGMA-B35CLzqQ.js.br +0 -0
  57. package/out/renderer/assets/erDiagram-SMLLAGMA-B35CLzqQ.js.gz +0 -0
  58. package/out/renderer/assets/{flowDiagram-DWJPFMVM-T3H9Pqwa.js → flowDiagram-DWJPFMVM-BidIy8zc.js} +6 -6
  59. package/out/renderer/assets/flowDiagram-DWJPFMVM-BidIy8zc.js.br +0 -0
  60. package/out/renderer/assets/flowDiagram-DWJPFMVM-BidIy8zc.js.gz +0 -0
  61. package/out/renderer/assets/{ganttDiagram-T4ZO3ILL-Hh-AJvLC.js → ganttDiagram-T4ZO3ILL-CqV1ei6S.js} +2 -2
  62. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-CqV1ei6S.js.br +0 -0
  63. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-CqV1ei6S.js.gz +0 -0
  64. package/out/renderer/assets/{gitGraphDiagram-UUTBAWPF-BDXB9jT_.js → gitGraphDiagram-UUTBAWPF-7wQ8gKPV.js} +6 -6
  65. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-7wQ8gKPV.js.br +0 -0
  66. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-7wQ8gKPV.js.gz +0 -0
  67. package/out/renderer/assets/{graph-MWvZ47Hf.js → graph-Ck9_bXv5.js} +2 -2
  68. package/out/renderer/assets/graph-Ck9_bXv5.js.br +0 -0
  69. package/out/renderer/assets/graph-Ck9_bXv5.js.gz +0 -0
  70. package/out/renderer/assets/{highlighted-body-OFNGDK62-Bvl34wyh.js → highlighted-body-OFNGDK62-gS-2OBX1.js} +1 -1
  71. package/out/renderer/assets/{index-BTEKdfpj.css → index-BtjFxpR5.css} +1 -1
  72. package/out/renderer/assets/index-BtjFxpR5.css.br +0 -0
  73. package/out/renderer/assets/index-BtjFxpR5.css.gz +0 -0
  74. package/out/renderer/assets/{index-BpPCAjGn.js → index-Cy_TZSUE.js} +2040 -1485
  75. package/out/renderer/assets/index-Cy_TZSUE.js.br +0 -0
  76. package/out/renderer/assets/index-Cy_TZSUE.js.gz +0 -0
  77. package/out/renderer/assets/{infoDiagram-42DDH7IO-Ca_9-363.js → infoDiagram-42DDH7IO-DlKxzT4w.js} +4 -4
  78. package/out/renderer/assets/{ishikawaDiagram-UXIWVN3A-D3GtyA4e.js → ishikawaDiagram-UXIWVN3A-DmOMlIE8.js} +1 -1
  79. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-DmOMlIE8.js.br +0 -0
  80. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-DmOMlIE8.js.gz +0 -0
  81. package/out/renderer/assets/{journeyDiagram-VCZTEJTY-DkQAlc0b.js → journeyDiagram-VCZTEJTY-CYRPGJN7.js} +4 -4
  82. package/out/renderer/assets/journeyDiagram-VCZTEJTY-CYRPGJN7.js.br +0 -0
  83. package/out/renderer/assets/journeyDiagram-VCZTEJTY-CYRPGJN7.js.gz +0 -0
  84. package/out/renderer/assets/{kanban-definition-6JOO6SKY-DamLzi6S.js → kanban-definition-6JOO6SKY-Dovb_i6Z.js} +2 -2
  85. package/out/renderer/assets/kanban-definition-6JOO6SKY-Dovb_i6Z.js.br +0 -0
  86. package/out/renderer/assets/kanban-definition-6JOO6SKY-Dovb_i6Z.js.gz +0 -0
  87. package/out/renderer/assets/{layout-Dw_ZcO_L.js → layout-BUs47sjz.js} +4 -4
  88. package/out/renderer/assets/layout-BUs47sjz.js.br +0 -0
  89. package/out/renderer/assets/layout-BUs47sjz.js.gz +0 -0
  90. package/out/renderer/assets/{linear-Dh5vwFy4.js → linear-CO24wS_v.js} +1 -1
  91. package/out/renderer/assets/linear-CO24wS_v.js.br +0 -0
  92. package/out/renderer/assets/linear-CO24wS_v.js.gz +0 -0
  93. package/out/renderer/assets/{min-DDCW5FhP.js → min-Dd_ATNHv.js} +2 -2
  94. package/out/renderer/assets/min-Dd_ATNHv.js.br +0 -0
  95. package/out/renderer/assets/min-Dd_ATNHv.js.gz +0 -0
  96. package/out/renderer/assets/{mindmap-definition-QFDTVHPH-B3rcYXPK.js → mindmap-definition-QFDTVHPH-CC3W7LA-.js} +3 -3
  97. package/out/renderer/assets/mindmap-definition-QFDTVHPH-CC3W7LA-.js.br +0 -0
  98. package/out/renderer/assets/mindmap-definition-QFDTVHPH-CC3W7LA-.js.gz +0 -0
  99. package/out/renderer/assets/{pieDiagram-DEJITSTG-CsCXUSKq.js → pieDiagram-DEJITSTG-BN6Ummnw.js} +6 -6
  100. package/out/renderer/assets/pieDiagram-DEJITSTG-BN6Ummnw.js.br +0 -0
  101. package/out/renderer/assets/pieDiagram-DEJITSTG-BN6Ummnw.js.gz +0 -0
  102. package/out/renderer/assets/{quadrantDiagram-34T5L4WZ-B91qjO1u.js → quadrantDiagram-34T5L4WZ-DTE_dLJv.js} +2 -2
  103. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-DTE_dLJv.js.br +0 -0
  104. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-DTE_dLJv.js.gz +0 -0
  105. package/out/renderer/assets/{requirementDiagram-MS252O5E-oDcN7qN5.js → requirementDiagram-MS252O5E-DVDS2RYN.js} +3 -3
  106. package/out/renderer/assets/requirementDiagram-MS252O5E-DVDS2RYN.js.br +0 -0
  107. package/out/renderer/assets/requirementDiagram-MS252O5E-DVDS2RYN.js.gz +0 -0
  108. package/out/renderer/assets/{sankeyDiagram-XADWPNL6-DNQO_6oX.js → sankeyDiagram-XADWPNL6-D4_LywJM.js} +1 -1
  109. package/out/renderer/assets/sankeyDiagram-XADWPNL6-D4_LywJM.js.br +0 -0
  110. package/out/renderer/assets/sankeyDiagram-XADWPNL6-D4_LywJM.js.gz +0 -0
  111. package/out/renderer/assets/{sequenceDiagram-FGHM5R23-DCh5u6wY.js → sequenceDiagram-FGHM5R23-89GBJZmd.js} +3 -3
  112. package/out/renderer/assets/sequenceDiagram-FGHM5R23-89GBJZmd.js.br +0 -0
  113. package/out/renderer/assets/sequenceDiagram-FGHM5R23-89GBJZmd.js.gz +0 -0
  114. package/out/renderer/assets/{stateDiagram-FHFEXIEX-DV0gaxkj.js → stateDiagram-FHFEXIEX-YKrUbogP.js} +8 -8
  115. package/out/renderer/assets/stateDiagram-FHFEXIEX-YKrUbogP.js.br +0 -0
  116. package/out/renderer/assets/stateDiagram-FHFEXIEX-YKrUbogP.js.gz +0 -0
  117. package/out/renderer/assets/{stateDiagram-v2-QKLJ7IA2-D1Sk_TKE.js → stateDiagram-v2-QKLJ7IA2-CO0pZRqI.js} +4 -4
  118. package/out/renderer/assets/{timeline-definition-GMOUNBTQ-Nq47TkPV.js → timeline-definition-GMOUNBTQ-BW2oxhj-.js} +2 -2
  119. package/out/renderer/assets/timeline-definition-GMOUNBTQ-BW2oxhj-.js.br +0 -0
  120. package/out/renderer/assets/timeline-definition-GMOUNBTQ-BW2oxhj-.js.gz +0 -0
  121. package/out/renderer/assets/{vennDiagram-DHZGUBPP-CMbmY-R_.js → vennDiagram-DHZGUBPP-DSy9zL6k.js} +1 -1
  122. package/out/renderer/assets/vennDiagram-DHZGUBPP-DSy9zL6k.js.br +0 -0
  123. package/out/renderer/assets/vennDiagram-DHZGUBPP-DSy9zL6k.js.gz +0 -0
  124. package/out/renderer/assets/{wardley-RL74JXVD-aLLqbf8o.js → wardley-RL74JXVD-DFRGDO55.js} +3 -3
  125. package/out/renderer/assets/wardley-RL74JXVD-DFRGDO55.js.br +0 -0
  126. package/out/renderer/assets/wardley-RL74JXVD-DFRGDO55.js.gz +0 -0
  127. package/out/renderer/assets/{wardleyDiagram-NUSXRM2D-8Kc4VQIw.js → wardleyDiagram-NUSXRM2D-CJUPdnii.js} +5 -5
  128. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-CJUPdnii.js.br +0 -0
  129. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-CJUPdnii.js.gz +0 -0
  130. package/out/renderer/assets/{xychartDiagram-5P7HB3ND-YtEoXmYf.js → xychartDiagram-5P7HB3ND-UGlSGsDE.js} +2 -2
  131. package/out/renderer/assets/xychartDiagram-5P7HB3ND-UGlSGsDE.js.br +0 -0
  132. package/out/renderer/assets/xychartDiagram-5P7HB3ND-UGlSGsDE.js.gz +0 -0
  133. package/out/renderer/index.html +2 -2
  134. package/out/renderer/index.html.br +0 -0
  135. package/out/renderer/index.html.gz +0 -0
  136. package/out/scripts/mcp-search/server.mjs +46 -46
  137. package/out/server/main.js +1067 -318
  138. package/package.json +4 -1
  139. package/out/renderer/assets/_baseUniq-JI50qq3v.js.br +0 -0
  140. package/out/renderer/assets/_baseUniq-JI50qq3v.js.gz +0 -0
  141. package/out/renderer/assets/arc-D82BffDI.js.br +0 -0
  142. package/out/renderer/assets/arc-D82BffDI.js.gz +0 -0
  143. package/out/renderer/assets/architectureDiagram-Q4EWVU46-BBRMDHvv.js.br +0 -0
  144. package/out/renderer/assets/architectureDiagram-Q4EWVU46-BBRMDHvv.js.gz +0 -0
  145. package/out/renderer/assets/blockDiagram-DXYQGD6D-CiCuaiyL.js.br +0 -0
  146. package/out/renderer/assets/blockDiagram-DXYQGD6D-CiCuaiyL.js.gz +0 -0
  147. package/out/renderer/assets/c4Diagram-AHTNJAMY-D9PM_R8p.js.br +0 -0
  148. package/out/renderer/assets/c4Diagram-AHTNJAMY-D9PM_R8p.js.gz +0 -0
  149. package/out/renderer/assets/chunk-4TB4RGXK-CxHdBbdg.js.br +0 -0
  150. package/out/renderer/assets/chunk-4TB4RGXK-CxHdBbdg.js.gz +0 -0
  151. package/out/renderer/assets/chunk-EDXVE4YY-DUOS0pBH.js.br +0 -0
  152. package/out/renderer/assets/chunk-EDXVE4YY-DUOS0pBH.js.gz +0 -0
  153. package/out/renderer/assets/chunk-OYMX7WX6-DH9JMSMI.js.br +0 -0
  154. package/out/renderer/assets/chunk-OYMX7WX6-DH9JMSMI.js.gz +0 -0
  155. package/out/renderer/assets/chunk-YZCP3GAM-B1pm_POM.js.br +0 -0
  156. package/out/renderer/assets/chunk-YZCP3GAM-B1pm_POM.js.gz +0 -0
  157. package/out/renderer/assets/cose-bilkent-S5V4N54A-ljZi9cz-.js.br +0 -0
  158. package/out/renderer/assets/cose-bilkent-S5V4N54A-ljZi9cz-.js.gz +0 -0
  159. package/out/renderer/assets/dagre-KV5264BT-DqnNoP69.js.br +0 -0
  160. package/out/renderer/assets/dagre-KV5264BT-DqnNoP69.js.gz +0 -0
  161. package/out/renderer/assets/diagram-5BDNPKRD-pBYJseHI.js.br +0 -0
  162. package/out/renderer/assets/diagram-5BDNPKRD-pBYJseHI.js.gz +0 -0
  163. package/out/renderer/assets/diagram-G4DWMVQ6-IPm9zWeG.js.br +0 -0
  164. package/out/renderer/assets/diagram-G4DWMVQ6-IPm9zWeG.js.gz +0 -0
  165. package/out/renderer/assets/diagram-MMDJMWI5-DSH58P_m.js.br +0 -0
  166. package/out/renderer/assets/diagram-MMDJMWI5-DSH58P_m.js.gz +0 -0
  167. package/out/renderer/assets/diagram-TYMM5635-Czl-GGCp.js.br +0 -0
  168. package/out/renderer/assets/diagram-TYMM5635-Czl-GGCp.js.gz +0 -0
  169. package/out/renderer/assets/erDiagram-SMLLAGMA-BENPNKae.js.br +0 -0
  170. package/out/renderer/assets/erDiagram-SMLLAGMA-BENPNKae.js.gz +0 -0
  171. package/out/renderer/assets/flowDiagram-DWJPFMVM-T3H9Pqwa.js.br +0 -0
  172. package/out/renderer/assets/flowDiagram-DWJPFMVM-T3H9Pqwa.js.gz +0 -0
  173. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-Hh-AJvLC.js.br +0 -0
  174. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-Hh-AJvLC.js.gz +0 -0
  175. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-BDXB9jT_.js.br +0 -0
  176. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-BDXB9jT_.js.gz +0 -0
  177. package/out/renderer/assets/graph-MWvZ47Hf.js.br +0 -0
  178. package/out/renderer/assets/graph-MWvZ47Hf.js.gz +0 -0
  179. package/out/renderer/assets/index-BTEKdfpj.css.br +0 -0
  180. package/out/renderer/assets/index-BTEKdfpj.css.gz +0 -0
  181. package/out/renderer/assets/index-BpPCAjGn.js.br +0 -0
  182. package/out/renderer/assets/index-BpPCAjGn.js.gz +0 -0
  183. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-D3GtyA4e.js.br +0 -0
  184. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-D3GtyA4e.js.gz +0 -0
  185. package/out/renderer/assets/journeyDiagram-VCZTEJTY-DkQAlc0b.js.br +0 -0
  186. package/out/renderer/assets/journeyDiagram-VCZTEJTY-DkQAlc0b.js.gz +0 -0
  187. package/out/renderer/assets/kanban-definition-6JOO6SKY-DamLzi6S.js.br +0 -0
  188. package/out/renderer/assets/kanban-definition-6JOO6SKY-DamLzi6S.js.gz +0 -0
  189. package/out/renderer/assets/layout-Dw_ZcO_L.js.br +0 -0
  190. package/out/renderer/assets/layout-Dw_ZcO_L.js.gz +0 -0
  191. package/out/renderer/assets/linear-Dh5vwFy4.js.br +0 -0
  192. package/out/renderer/assets/linear-Dh5vwFy4.js.gz +0 -0
  193. package/out/renderer/assets/min-DDCW5FhP.js.br +0 -0
  194. package/out/renderer/assets/min-DDCW5FhP.js.gz +0 -0
  195. package/out/renderer/assets/mindmap-definition-QFDTVHPH-B3rcYXPK.js.br +0 -0
  196. package/out/renderer/assets/mindmap-definition-QFDTVHPH-B3rcYXPK.js.gz +0 -0
  197. package/out/renderer/assets/pieDiagram-DEJITSTG-CsCXUSKq.js.br +0 -0
  198. package/out/renderer/assets/pieDiagram-DEJITSTG-CsCXUSKq.js.gz +0 -0
  199. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-B91qjO1u.js.br +0 -0
  200. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-B91qjO1u.js.gz +0 -0
  201. package/out/renderer/assets/requirementDiagram-MS252O5E-oDcN7qN5.js.br +0 -0
  202. package/out/renderer/assets/requirementDiagram-MS252O5E-oDcN7qN5.js.gz +0 -0
  203. package/out/renderer/assets/sankeyDiagram-XADWPNL6-DNQO_6oX.js.br +0 -0
  204. package/out/renderer/assets/sankeyDiagram-XADWPNL6-DNQO_6oX.js.gz +0 -0
  205. package/out/renderer/assets/sequenceDiagram-FGHM5R23-DCh5u6wY.js.br +0 -0
  206. package/out/renderer/assets/sequenceDiagram-FGHM5R23-DCh5u6wY.js.gz +0 -0
  207. package/out/renderer/assets/stateDiagram-FHFEXIEX-DV0gaxkj.js.br +0 -0
  208. package/out/renderer/assets/stateDiagram-FHFEXIEX-DV0gaxkj.js.gz +0 -0
  209. package/out/renderer/assets/timeline-definition-GMOUNBTQ-Nq47TkPV.js.br +0 -0
  210. package/out/renderer/assets/timeline-definition-GMOUNBTQ-Nq47TkPV.js.gz +0 -0
  211. package/out/renderer/assets/vennDiagram-DHZGUBPP-CMbmY-R_.js.br +0 -0
  212. package/out/renderer/assets/vennDiagram-DHZGUBPP-CMbmY-R_.js.gz +0 -0
  213. package/out/renderer/assets/wardley-RL74JXVD-aLLqbf8o.js.br +0 -0
  214. package/out/renderer/assets/wardley-RL74JXVD-aLLqbf8o.js.gz +0 -0
  215. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-8Kc4VQIw.js.br +0 -0
  216. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-8Kc4VQIw.js.gz +0 -0
  217. package/out/renderer/assets/xychartDiagram-5P7HB3ND-YtEoXmYf.js.br +0 -0
  218. package/out/renderer/assets/xychartDiagram-5P7HB3ND-YtEoXmYf.js.gz +0 -0
@@ -57,6 +57,9 @@ var DEFAULT_SETTINGS = {
57
57
  volume: 50,
58
58
  muted: false,
59
59
  theme: "soft"
60
+ },
61
+ proxy: {
62
+ mode: "off"
60
63
  }
61
64
  };
62
65
  function settingsPath() {
@@ -188,6 +191,20 @@ function readSettings() {
188
191
  theme: raw2.theme === "soft" || raw2.theme === "crisp" ? raw2.theme : DEFAULT_SETTINGS.sound.theme
189
192
  };
190
193
  })();
194
+ const proxy = (() => {
195
+ const raw2 = rawObj && isObject(rawObj.proxy) ? rawObj.proxy : null;
196
+ if (!raw2) return DEFAULT_SETTINGS.proxy;
197
+ const mode = raw2.mode === "off" || raw2.mode === "manual" || raw2.mode === "system" ? raw2.mode : DEFAULT_SETTINGS.proxy.mode;
198
+ const str = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
199
+ return {
200
+ mode,
201
+ httpProxy: str(raw2.httpProxy),
202
+ httpsProxy: str(raw2.httpsProxy),
203
+ noProxy: str(raw2.noProxy),
204
+ username: str(raw2.username),
205
+ password: str(raw2.password)
206
+ };
207
+ })();
191
208
  const snippets = Array.isArray(rawObj?.snippets) ? rawObj.snippets.filter(
192
209
  (s) => isObject(s) && typeof s.id === "string" && typeof s.title === "string" && typeof s.content === "string"
193
210
  ) : [];
@@ -230,6 +247,7 @@ function readSettings() {
230
247
  ilink,
231
248
  editor,
232
249
  sound,
250
+ proxy,
233
251
  snippets,
234
252
  imageGeneration
235
253
  };
@@ -321,6 +339,7 @@ function getSettings() {
321
339
  muted: meta.sound.muted,
322
340
  theme: meta.sound.theme
323
341
  },
342
+ proxy: meta.proxy ?? DEFAULT_SETTINGS.proxy,
324
343
  snippets: meta.snippets ?? [],
325
344
  imageGeneration: (meta.imageGeneration ?? []).map((p) => ({
326
345
  id: p.id,
@@ -461,6 +480,21 @@ function updateSettings(settings) {
461
480
  theme: settings.sound.theme === "soft" || settings.sound.theme === "crisp" ? settings.sound.theme : prevMeta.sound.theme
462
481
  };
463
482
  })(),
483
+ proxy: (() => {
484
+ if (!settings.proxy) {
485
+ return prevMeta.proxy;
486
+ }
487
+ const mode = settings.proxy.mode === "off" || settings.proxy.mode === "manual" || settings.proxy.mode === "system" ? settings.proxy.mode : prevMeta.proxy?.mode ?? DEFAULT_SETTINGS.proxy.mode;
488
+ const str = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
489
+ return {
490
+ mode,
491
+ httpProxy: str(settings.proxy.httpProxy),
492
+ httpsProxy: str(settings.proxy.httpsProxy),
493
+ noProxy: str(settings.proxy.noProxy),
494
+ username: str(settings.proxy.username),
495
+ password: str(settings.proxy.password)
496
+ };
497
+ })(),
464
498
  snippets: settings.snippets ?? prevMeta.snippets,
465
499
  imageGeneration: settings.imageGeneration ? settings.imageGeneration.map((p) => ({
466
500
  id: p.id,
@@ -1505,19 +1539,6 @@ import { relative as relative2, resolve as resolve2, isAbsolute as isAbsolute2 }
1505
1539
  function toPosixPath(p) {
1506
1540
  return p.replace(/\\/g, "/");
1507
1541
  }
1508
- var IGNORE_NAME_SET = /* @__PURE__ */ new Set([".git", ".svn", ".hg", "node_modules", "vendor", "__pycache__"]);
1509
- function isIgnorePath(fullPath, cwd) {
1510
- if (fullPath === cwd) return false;
1511
- const relPath = relative2(cwd, fullPath);
1512
- if (!relPath) return false;
1513
- const segments = relPath.split(/[\\/]+/);
1514
- for (let i = 0; i < segments.length; i++) {
1515
- const name = segments[i];
1516
- if (!name || name === ".") continue;
1517
- if (IGNORE_NAME_SET.has(name)) return true;
1518
- }
1519
- return false;
1520
- }
1521
1542
  function resolveSafePath(cwd, relativePath) {
1522
1543
  const safeCwd = resolve2(cwd);
1523
1544
  const fullPath = resolve2(safeCwd, relativePath || "");
@@ -1779,11 +1800,11 @@ function createWebUIModule() {
1779
1800
  }
1780
1801
  });
1781
1802
  });
1782
- return new Promise((resolve8, reject) => {
1803
+ return new Promise((resolve9, reject) => {
1783
1804
  const listenPort = options?.port && options.port > 0 ? options.port : 0;
1784
1805
  httpServer.listen(listenPort, "0.0.0.0", () => {
1785
1806
  isEnabled = true;
1786
- resolve8({ url: getWebUIUrl(httpServer.address()) });
1807
+ resolve9({ url: getWebUIUrl(httpServer.address()) });
1787
1808
  });
1788
1809
  httpServer.on("error", reject);
1789
1810
  });
@@ -2168,7 +2189,7 @@ import { join as join12 } from "path";
2168
2189
 
2169
2190
  // src/shared/zod/mcp-search-schema.ts
2170
2191
  import { z } from "zod";
2171
- var searchRequestSchema = z.object({
2192
+ var grepRequestSchema = z.object({
2172
2193
  pattern: z.string().describe("Search pattern (literal text by default, set regex=true for regex)."),
2173
2194
  path: z.string().describe(
2174
2195
  "Directory or file(s) to search. Accepts: relative path (relative to project root), absolute path (POSIX or Windows), or file:// URI."
@@ -2183,20 +2204,10 @@ var searchRequestSchema = z.object({
2183
2204
  invertMatch: z.boolean().optional().describe("Show lines that do NOT match the pattern (-v)."),
2184
2205
  wordMatch: z.boolean().optional().describe("Only match whole words (-w).")
2185
2206
  });
2186
- var searchRespondSchema = z.object({
2207
+ var grepRespondSchema = z.object({
2187
2208
  output: z.string(),
2188
2209
  code: z.number()
2189
2210
  });
2190
- var rgRequestSchema = z.object({
2191
- args: z.array(z.string()).describe(
2192
- "Raw ripgrep CLI arguments (e.g. ['-i', 'pattern', 'src/']). The pattern and path are included in this array."
2193
- )
2194
- });
2195
- var rgRespondSchema = z.object({
2196
- output: z.string(),
2197
- code: z.number(),
2198
- stderr: z.string().optional()
2199
- });
2200
2211
  var fileOutlineRequestSchema = z.object({
2201
2212
  path: z.string().describe(
2202
2213
  "File path to analyze. Accepts: relative path (relative to project root), absolute path (POSIX or Windows), or file:// URI."
@@ -2205,6 +2216,20 @@ var fileOutlineRequestSchema = z.object({
2205
2216
  var fileOutlineRespondSchema = z.object({
2206
2217
  outline: z.string().describe("Structural outline of the file in text format.")
2207
2218
  });
2219
+ var globRequestSchema = z.object({
2220
+ pattern: z.string().describe("Glob pattern, e.g. '**/*.rs', 'src/**/*.{ts,tsx}'."),
2221
+ path: z.string().optional().describe("Root directory to search from. Defaults to project root."),
2222
+ limit: z.number().int().positive().optional().describe("Maximum number of results to return."),
2223
+ maxDepth: z.number().int().positive().optional().describe("Maximum directory depth to traverse."),
2224
+ dot: z.boolean().optional().describe("Include dotfiles (hidden files/directories). Default: false."),
2225
+ onlyFiles: z.boolean().optional().describe("Only match files, not directories. Default: false (includes directories)."),
2226
+ gitignore: z.boolean().optional().describe("Respect .gitignore patterns. Default: true.")
2227
+ });
2228
+ var globRespondSchema = z.object({
2229
+ filePaths: z.array(z.string()),
2230
+ totalFiles: z.number(),
2231
+ truncated: z.boolean()
2232
+ });
2208
2233
 
2209
2234
  // src/backend/search/file-outline.ts
2210
2235
  import { extname, join as join10, isAbsolute as isAbsolute4, resolve as resolve3, relative as relative5 } from "path";
@@ -2627,7 +2652,7 @@ var LANGUAGES = [
2627
2652
  }
2628
2653
  ];
2629
2654
  async function parseInChild(filePath, config, cwd, timeout = 3e4) {
2630
- return new Promise((resolve8, reject) => {
2655
+ return new Promise((resolve9, reject) => {
2631
2656
  const modulePath = join10(process.scriptsPath, "/worker-file-outline/worker.mjs");
2632
2657
  const child = fork(modulePath, [], { execArgv: [], cwd });
2633
2658
  const timer = setTimeout(() => {
@@ -2636,7 +2661,7 @@ async function parseInChild(filePath, config, cwd, timeout = 3e4) {
2636
2661
  }, timeout);
2637
2662
  child.on("message", (msg) => {
2638
2663
  clearTimeout(timer);
2639
- if (msg.type === "result") resolve8({ symbols: msg.symbols, totalLines: msg.totalLines });
2664
+ if (msg.type === "result") resolve9({ symbols: msg.symbols, totalLines: msg.totalLines });
2640
2665
  else reject(new Error(msg.error));
2641
2666
  });
2642
2667
  child.on("error", (err) => {
@@ -2799,7 +2824,7 @@ import { join as join11, isAbsolute as isAbsolute5, resolve as resolve4, relativ
2799
2824
  import { fileURLToPath as fileURLToPath4 } from "url";
2800
2825
  import { fork as fork2 } from "child_process";
2801
2826
  function ripgrepInChild(args2, cwd, timeout = 3e4) {
2802
- return new Promise((resolve8, reject) => {
2827
+ return new Promise((resolve9, reject) => {
2803
2828
  const child = fork2(join11(process.scriptsPath, "worker-ripgrep/worker.mjs"), [], { cwd });
2804
2829
  const timer = setTimeout(() => {
2805
2830
  child.kill();
@@ -2808,7 +2833,7 @@ function ripgrepInChild(args2, cwd, timeout = 3e4) {
2808
2833
  child.on("message", (msg) => {
2809
2834
  clearTimeout(timer);
2810
2835
  if (msg.type === "error") reject(new Error(msg.error));
2811
- else resolve8({ code: msg.code, stdout: msg.stdout, stderr: msg.stderr });
2836
+ else resolve9({ code: msg.code, stdout: msg.stdout, stderr: msg.stderr });
2812
2837
  });
2813
2838
  child.on("error", (err) => {
2814
2839
  clearTimeout(timer);
@@ -2831,7 +2856,7 @@ function normalizePath2(inputPath, cwd) {
2831
2856
  }
2832
2857
  return resolve4(cwd ?? process.cwd(), inputPath);
2833
2858
  }
2834
- async function search(options) {
2859
+ async function grep(options) {
2835
2860
  const args2 = [];
2836
2861
  args2.push("--heading");
2837
2862
  args2.push("--line-number");
@@ -2853,16 +2878,38 @@ async function search(options) {
2853
2878
  const { code, stdout } = await ripgrepInChild(args2, options.projectDir, options.timeout);
2854
2879
  return { output: stdout || "", code };
2855
2880
  }
2856
- async function rg(options) {
2857
- const { code, stdout, stderr } = await ripgrepInChild(
2858
- options.args,
2859
- options.projectDir,
2860
- options.timeout
2861
- );
2881
+
2882
+ // src/backend/search/glob.ts
2883
+ import { globby } from "globby";
2884
+ import { isAbsolute as isAbsolute6, resolve as resolve5 } from "path";
2885
+ import { fileURLToPath as fileURLToPath5 } from "url";
2886
+ function normalizePath3(inputPath, cwd) {
2887
+ if (inputPath.startsWith("file://")) {
2888
+ return fileURLToPath5(inputPath);
2889
+ }
2890
+ if (isAbsolute6(inputPath)) {
2891
+ return inputPath;
2892
+ }
2893
+ return resolve5(cwd ?? process.cwd(), inputPath);
2894
+ }
2895
+ async function glob(options) {
2896
+ const cwd = options.path ? normalizePath3(options.path, options.projectDir) : options.projectDir;
2897
+ const entries = await globby(options.pattern, {
2898
+ cwd,
2899
+ dot: options.dot ?? false,
2900
+ onlyFiles: options.onlyFiles ?? false,
2901
+ markDirectories: true,
2902
+ gitignore: options.gitignore ?? true,
2903
+ deep: options.maxDepth
2904
+ });
2905
+ entries.sort();
2906
+ const limit = options.limit ?? 500;
2907
+ const truncated = entries.length > limit;
2908
+ const filePaths = truncated ? entries.slice(0, limit) : entries;
2862
2909
  return {
2863
- output: stdout || "",
2864
- code,
2865
- stderr: stderr || void 0
2910
+ filePaths,
2911
+ totalFiles: entries.length,
2912
+ truncated
2866
2913
  };
2867
2914
  }
2868
2915
 
@@ -2871,21 +2918,21 @@ function createSearchModule(_ctx) {
2871
2918
  return { registerSearchRoute, buildSearchMcpServer };
2872
2919
  }
2873
2920
  function registerSearchRoute(server, projectDir) {
2874
- server.registry("search/search", async (payload) => {
2875
- const params = searchRequestSchema.parse(payload);
2876
- const result = await search({ projectDir, ...params });
2877
- return searchRespondSchema.parse(result);
2878
- });
2879
- server.registry("search/rg", async (payload) => {
2880
- const params = rgRequestSchema.parse(payload);
2881
- const result = await rg({ projectDir, ...params });
2882
- return rgRespondSchema.parse(result);
2921
+ server.registry("search/grep", async (payload) => {
2922
+ const params = grepRequestSchema.parse(payload);
2923
+ const result = await grep({ projectDir, ...params });
2924
+ return grepRespondSchema.parse(result);
2883
2925
  });
2884
2926
  server.registry("search/file_outline", async (payload) => {
2885
2927
  const params = fileOutlineRequestSchema.parse(payload);
2886
2928
  const result = await fileOutline({ projectDir, ...params });
2887
2929
  return fileOutlineRespondSchema.parse(result);
2888
2930
  });
2931
+ server.registry("search/glob", async (payload) => {
2932
+ const params = globRequestSchema.parse(payload);
2933
+ const result = await glob({ projectDir, ...params });
2934
+ return globRespondSchema.parse(result);
2935
+ });
2889
2936
  }
2890
2937
  function buildSearchMcpServer(options) {
2891
2938
  return {
@@ -2948,7 +2995,11 @@ function createAskUserModule(ctx, deps) {
2948
2995
  async function askUser(options) {
2949
2996
  const { sessionId } = options;
2950
2997
  const askUserId = randomUUID2();
2951
- const request = { ...options, askUserId };
2998
+ const request = {
2999
+ ...options,
3000
+ askUserId,
3001
+ timeoutAt: Date.now() + USER_REQUEST_TIMEOUT_MS
3002
+ };
2952
3003
  sendEvent("ask-user-request", request);
2953
3004
  const ilinkBridge = deps.ilink.getBridge();
2954
3005
  const ilinkActiveSessionId = deps.ilink.getActiveSessionId();
@@ -2963,13 +3014,13 @@ function createAskUserModule(ctx, deps) {
2963
3014
  });
2964
3015
  }
2965
3016
  }
2966
- return new Promise((resolve8) => {
3017
+ return new Promise((resolve9) => {
2967
3018
  const timeoutId = setTimeout(() => {
2968
3019
  const pending = pendingRequests.get(askUserId);
2969
3020
  if (pending) {
2970
3021
  pendingRequests.delete(askUserId);
2971
3022
  const response = { value: null, reason: "timeout" };
2972
- resolve8(response);
3023
+ resolve9(response);
2973
3024
  sendEvent("ask-user-response", {
2974
3025
  sessionId,
2975
3026
  askUserId,
@@ -2980,7 +3031,7 @@ function createAskUserModule(ctx, deps) {
2980
3031
  console.warn(`[askUser] timeout fired but no pending request found for ${askUserId}`);
2981
3032
  }
2982
3033
  }, USER_REQUEST_TIMEOUT_MS);
2983
- pendingRequests.set(askUserId, { resolve: resolve8, timeoutId, sessionId, request });
3034
+ pendingRequests.set(askUserId, { resolve: resolve9, timeoutId, sessionId, request });
2984
3035
  });
2985
3036
  }
2986
3037
  async function getPendingAskUserRequests({ sessionId }) {
@@ -3048,8 +3099,8 @@ function createAskUserModule(ctx, deps) {
3048
3099
 
3049
3100
  // src/backend/share-to-user.ts
3050
3101
  import { randomUUID as randomUUID3 } from "crypto";
3051
- import { join as join14 } from "path";
3052
- import { fileURLToPath as fileURLToPath5 } from "url";
3102
+ import { join as join14, relative as relative7, isAbsolute as isAbsolute7 } from "path";
3103
+ import { fileURLToPath as fileURLToPath6 } from "url";
3053
3104
  import { readFile as readFile5, writeFile } from "fs/promises";
3054
3105
  import { existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
3055
3106
  import * as mimeTypes3 from "mime-types";
@@ -3098,23 +3149,29 @@ function createShareToUserModule(ctx, deps) {
3098
3149
  const { sessionId, type, uri, data, name, mimeType } = options;
3099
3150
  const resolvedMimeType = resolveMimeType(name, mimeType);
3100
3151
  if (type === "project" && uri) {
3152
+ const session = storage.getSession(sessionId);
3153
+ if (!session) throw new Error(`Session not found: ${sessionId}`);
3154
+ let projectPath = uri.startsWith("file://") ? fileURLToPath6(uri) : uri;
3155
+ if (isAbsolute7(projectPath)) {
3156
+ const rel = relative7(session.cwd, projectPath);
3157
+ if (!rel.startsWith("..") && !isAbsolute7(rel)) {
3158
+ projectPath = rel;
3159
+ }
3160
+ }
3101
3161
  const ilinkBridge2 = deps.ilink.getBridge();
3102
3162
  const ilinkActiveSessionId2 = deps.ilink.getActiveSessionId();
3103
3163
  if (ilinkBridge2?.isConnected && sessionId === ilinkActiveSessionId2) {
3104
3164
  const toUserId = ilinkBridge2.userId;
3105
3165
  if (toUserId) {
3106
- const session = storage.getSession(sessionId);
3107
- if (session) {
3108
- deps.ilink.appendMediaBuffer({
3109
- filePath: join14(session.cwd, uri),
3110
- name,
3111
- toUserId,
3112
- mimeType: resolvedMimeType
3113
- });
3114
- }
3166
+ deps.ilink.appendMediaBuffer({
3167
+ filePath: join14(session.cwd, projectPath),
3168
+ name,
3169
+ toUserId,
3170
+ mimeType: resolvedMimeType
3171
+ });
3115
3172
  }
3116
3173
  }
3117
- return { name, projectPath: uri, mimeType: resolvedMimeType };
3174
+ return { name, projectPath, mimeType: resolvedMimeType };
3118
3175
  }
3119
3176
  const shareId = randomUUID3();
3120
3177
  const shareDir = storage.sessionShareDir(sessionId);
@@ -3132,7 +3189,7 @@ function createShareToUserModule(ctx, deps) {
3132
3189
  if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
3133
3190
  buffer = Buffer.from(await response.arrayBuffer());
3134
3191
  } else {
3135
- const sourcePath = uri.startsWith("file://") ? fileURLToPath5(uri) : uri;
3192
+ const sourcePath = uri.startsWith("file://") ? fileURLToPath6(uri) : uri;
3136
3193
  buffer = await readFile5(sourcePath);
3137
3194
  }
3138
3195
  } catch (err) {
@@ -3224,9 +3281,9 @@ function spawnStdioAgent(options) {
3224
3281
  proc.stdin.end();
3225
3282
  } catch {
3226
3283
  }
3227
- await new Promise((resolve8) => {
3284
+ await new Promise((resolve9) => {
3228
3285
  if (proc.exitCode !== null) {
3229
- resolve8();
3286
+ resolve9();
3230
3287
  return;
3231
3288
  }
3232
3289
  let killTimer = null;
@@ -3234,13 +3291,13 @@ function spawnStdioAgent(options) {
3234
3291
  if (killTimer) {
3235
3292
  clearTimeout(killTimer);
3236
3293
  }
3237
- resolve8();
3294
+ resolve9();
3238
3295
  };
3239
3296
  proc.once("exit", onExit);
3240
3297
  killProcessGroup(proc, "SIGTERM");
3241
3298
  killTimer = setTimeout(() => {
3242
3299
  killProcessGroup(proc, "SIGKILL");
3243
- resolve8();
3300
+ resolve9();
3244
3301
  }, 2e3);
3245
3302
  });
3246
3303
  }
@@ -3356,7 +3413,7 @@ var AgentClientProxy = class {
3356
3413
  };
3357
3414
 
3358
3415
  // src/agents/acp-client-tools.ts
3359
- import { resolve as resolve5 } from "path";
3416
+ import { resolve as resolve6 } from "path";
3360
3417
  import { tool } from "ai";
3361
3418
  import { z as z4 } from "zod";
3362
3419
 
@@ -3549,7 +3606,7 @@ Always prefer using line/limit to read specific sections, or use the Search MCP'
3549
3606
  if (!connection) {
3550
3607
  throw new Error("ACP connection is not available.");
3551
3608
  }
3552
- const filename = resolve5(cwd ?? params.cwd, path2);
3609
+ const filename = resolve6(cwd ?? params.cwd, path2);
3553
3610
  let title = `ReadFile ${filename}`;
3554
3611
  if (line || limit) {
3555
3612
  title += `:${line ?? 0}`;
@@ -3656,7 +3713,7 @@ Always prefer using line/limit to read specific sections, or use the Search MCP'
3656
3713
  if (!connection) {
3657
3714
  throw new Error("ACP connection is not available.");
3658
3715
  }
3659
- const filename = resolve5(cwd ?? params.cwd, path2);
3716
+ const filename = resolve6(cwd ?? params.cwd, path2);
3660
3717
  let title = `WriteFile ${filename}`;
3661
3718
  const toolCall = {
3662
3719
  toolCallId,
@@ -3741,7 +3798,7 @@ Use exact string matching for oldText and set replaceAll=true when needed.`,
3741
3798
  if (!connection) {
3742
3799
  throw new Error("ACP connection is not available.");
3743
3800
  }
3744
- const filename = resolve5(cwd ?? params.cwd, path2);
3801
+ const filename = resolve6(cwd ?? params.cwd, path2);
3745
3802
  const title = `EditFile ${filename}`;
3746
3803
  const toolCall = {
3747
3804
  toolCallId,
@@ -3921,8 +3978,8 @@ Avoid destructive commands and prefer deterministic, non-interactive commands.`,
3921
3978
  try {
3922
3979
  const waitPromise = terminal.waitForExit();
3923
3980
  if (timeoutMs) {
3924
- const timeoutPromise = new Promise((resolve8) => {
3925
- setTimeout(() => resolve8(null), timeoutMs);
3981
+ const timeoutPromise = new Promise((resolve9) => {
3982
+ setTimeout(() => resolve9(null), timeoutMs);
3926
3983
  });
3927
3984
  const waitResult = await Promise.race([waitPromise, timeoutPromise]);
3928
3985
  if (waitResult === null) {
@@ -4041,6 +4098,208 @@ async function closeACPClientTools(session) {
4041
4098
  import { createMCPClient } from "@ai-sdk/mcp";
4042
4099
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
4043
4100
  import { ContentBlockSchema } from "@modelcontextprotocol/sdk/types.js";
4101
+
4102
+ // src/backend/proxy.ts
4103
+ import { execFileSync as execFileSync2 } from "node:child_process";
4104
+ import http from "node:http";
4105
+ import https from "node:https";
4106
+ import { Agent as UndiciAgent, EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
4107
+ import { ProxyAgent as NodeProxyAgent } from "proxy-agent";
4108
+ var PROXY_ENV_KEYS = [
4109
+ "HTTP_PROXY",
4110
+ "HTTPS_PROXY",
4111
+ "NO_PROXY",
4112
+ "http_proxy",
4113
+ "https_proxy",
4114
+ "no_proxy"
4115
+ ];
4116
+ var currentConfig = { enabled: false };
4117
+ function settingProxyInfoToProxyConfig(input) {
4118
+ if (!input || input.mode === "off") return { enabled: false };
4119
+ const str = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
4120
+ return {
4121
+ enabled: true,
4122
+ httpProxy: str(input.httpProxy),
4123
+ httpsProxy: str(input.httpsProxy),
4124
+ noProxy: str(input.noProxy),
4125
+ username: str(input.username),
4126
+ password: str(input.password)
4127
+ };
4128
+ }
4129
+ function normalizeProxyUrl(raw) {
4130
+ if (!raw) return void 0;
4131
+ const trimmed = raw.trim();
4132
+ if (!trimmed) return void 0;
4133
+ let url;
4134
+ try {
4135
+ url = new URL(trimmed);
4136
+ } catch {
4137
+ try {
4138
+ url = new URL(`http://${trimmed}`);
4139
+ } catch {
4140
+ return void 0;
4141
+ }
4142
+ }
4143
+ if (url.protocol !== "http:" && url.protocol !== "https:") return void 0;
4144
+ return url.toString().replace(/\/+$/, "");
4145
+ }
4146
+ function withAuth(url, username, password) {
4147
+ if (!username) return url;
4148
+ try {
4149
+ const parsed = new URL(url);
4150
+ parsed.username = username;
4151
+ if (password) parsed.password = password;
4152
+ return parsed.toString().replace(/\/+$/, "");
4153
+ } catch {
4154
+ return url;
4155
+ }
4156
+ }
4157
+ function buildProxyEnv() {
4158
+ const config = currentConfig;
4159
+ if (config.enabled === false) return {};
4160
+ const httpProxy = normalizeProxyUrl(config.httpProxy);
4161
+ const httpsProxy = normalizeProxyUrl(config.httpsProxy ?? config.httpProxy);
4162
+ if (!httpProxy && !httpsProxy) return {};
4163
+ const noProxy = config.noProxy?.trim();
4164
+ const env = {};
4165
+ if (httpProxy) {
4166
+ const httpUrl = withAuth(httpProxy, config.username, config.password);
4167
+ if (httpUrl) {
4168
+ env.HTTP_PROXY = httpUrl;
4169
+ env.http_proxy = httpUrl;
4170
+ }
4171
+ }
4172
+ if (httpsProxy) {
4173
+ const httpsUrl = withAuth(httpsProxy, config.username, config.password);
4174
+ if (httpsUrl) {
4175
+ env.HTTPS_PROXY = httpsUrl;
4176
+ env.https_proxy = httpsUrl;
4177
+ }
4178
+ }
4179
+ if (noProxy) {
4180
+ env.NO_PROXY = noProxy;
4181
+ env.no_proxy = noProxy;
4182
+ }
4183
+ return env;
4184
+ }
4185
+ function setProcessEnv(env) {
4186
+ for (const key of PROXY_ENV_KEYS) {
4187
+ if (env[key]) {
4188
+ process.env[key] = env[key];
4189
+ } else {
4190
+ delete process.env[key];
4191
+ }
4192
+ }
4193
+ }
4194
+ function resetGlobalDispatchers() {
4195
+ setGlobalDispatcher(new UndiciAgent());
4196
+ http.globalAgent = new http.Agent();
4197
+ https.globalAgent = new https.Agent();
4198
+ }
4199
+ function enableGlobalDispatchers() {
4200
+ setGlobalDispatcher(new EnvHttpProxyAgent());
4201
+ http.globalAgent = new NodeProxyAgent();
4202
+ https.globalAgent = new NodeProxyAgent();
4203
+ }
4204
+ function applyProxy(config) {
4205
+ currentConfig = config;
4206
+ if (config.enabled === false) {
4207
+ setProcessEnv({});
4208
+ resetGlobalDispatchers();
4209
+ return;
4210
+ }
4211
+ const env = buildProxyEnv();
4212
+ if (Object.keys(env).length === 0) {
4213
+ setProcessEnv({});
4214
+ resetGlobalDispatchers();
4215
+ return;
4216
+ }
4217
+ setProcessEnv(env);
4218
+ enableGlobalDispatchers();
4219
+ }
4220
+ function detectSystemProxy() {
4221
+ const envHttp = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy;
4222
+ if (envHttp) {
4223
+ return {
4224
+ enabled: true,
4225
+ httpProxy: process.env.HTTP_PROXY || process.env.http_proxy || void 0,
4226
+ httpsProxy: process.env.HTTPS_PROXY || process.env.https_proxy || void 0,
4227
+ noProxy: process.env.NO_PROXY || process.env.no_proxy || void 0
4228
+ };
4229
+ }
4230
+ try {
4231
+ if (process.platform === "darwin") {
4232
+ const stdout = execFileSync2("scutil", ["--proxy"], { timeout: 3e3 }).toString();
4233
+ return parseScutilProxy(stdout);
4234
+ }
4235
+ if (process.platform === "win32") {
4236
+ const stdout = execFileSync2("netsh", ["winhttp", "show", "proxy"], {
4237
+ timeout: 3e3
4238
+ }).toString();
4239
+ return parseNetshProxy(stdout);
4240
+ }
4241
+ } catch {
4242
+ }
4243
+ return { enabled: false };
4244
+ }
4245
+ function parseScutilProxy(stdout) {
4246
+ const get = (key) => {
4247
+ const m = stdout.match(new RegExp(`^\\s*${key}\\s*:\\s*(.+)$`, "m"));
4248
+ return m ? m[1].trim() : void 0;
4249
+ };
4250
+ const host = (key) => {
4251
+ const value = get(key);
4252
+ if (!value || value === "<null>") return void 0;
4253
+ return value.replace(/^"|"$/g, "");
4254
+ };
4255
+ const port2 = (key) => {
4256
+ const value = get(key);
4257
+ return value && value !== "0" ? value : void 0;
4258
+ };
4259
+ const build = (enableKey, hostKey, portKey) => {
4260
+ if (get(enableKey) !== "1") return void 0;
4261
+ const h = host(hostKey);
4262
+ if (!h) return void 0;
4263
+ const p = port2(portKey);
4264
+ let proxyUrl = `http://${h}`;
4265
+ if (p) {
4266
+ proxyUrl += `:${p}`;
4267
+ }
4268
+ return proxyUrl;
4269
+ };
4270
+ const httpProxy = build("HTTPEnable", "HTTPProxy", "HTTPPort");
4271
+ const httpsProxy = build("HTTPSEnable", "HTTPSProxy", "HTTPSPort");
4272
+ if (!httpProxy && !httpsProxy) return { enabled: false };
4273
+ return { enabled: true, httpProxy, httpsProxy };
4274
+ }
4275
+ function parseNetshProxy(stdout) {
4276
+ const match = stdout.match(/Proxy\s*Server\(s\)\s*:\s*(.+)$/m);
4277
+ if (!match) return { enabled: false };
4278
+ const raw = match[1].trim();
4279
+ if (!raw || raw === "<none>") return { enabled: false };
4280
+ let httpProxy;
4281
+ let httpsProxy;
4282
+ for (const part of raw.split(";")) {
4283
+ const trimmed = part.trim();
4284
+ if (!trimmed) continue;
4285
+ const eq = trimmed.indexOf("=");
4286
+ if (eq === -1) {
4287
+ httpProxy = `http://${trimmed}`;
4288
+ httpsProxy = `http://${trimmed}`;
4289
+ } else {
4290
+ const scheme = trimmed.slice(0, eq).trim().toLowerCase();
4291
+ const value = trimmed.slice(eq + 1).trim();
4292
+ if (scheme === "http") httpProxy = `http://${value}`;
4293
+ else if (scheme === "https") httpsProxy = `http://${value}`;
4294
+ }
4295
+ }
4296
+ const bypass = stdout.match(/Bypass\s*List\s*:\s*(.+)$/m);
4297
+ const noProxy = bypass ? bypass[1].trim().replace(/<local>/g, "localhost,127.0.0.1") : void 0;
4298
+ if (!httpProxy && !httpsProxy) return { enabled: false };
4299
+ return { enabled: true, httpProxy, httpsProxy, noProxy };
4300
+ }
4301
+
4302
+ // src/agents/mcp-tools.ts
4044
4303
  function sanitizeName(input) {
4045
4304
  return input.trim().toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
4046
4305
  }
@@ -4060,7 +4319,7 @@ function toEnvRecord(env) {
4060
4319
  }
4061
4320
  function inferToolKind(name) {
4062
4321
  const normalized = name.toLowerCase();
4063
- if (normalized.includes("read") || normalized.includes("list") || normalized.includes("search")) {
4322
+ if (normalized.includes("read") || normalized.includes("list") || normalized.includes("search") || normalized.includes("grep") || normalized.includes("glob")) {
4064
4323
  return "read";
4065
4324
  }
4066
4325
  if (normalized.includes("write") || normalized.includes("edit") || normalized.includes("update")) {
@@ -4090,7 +4349,10 @@ async function createClient(server, cwd) {
4090
4349
  transport: new StdioClientTransport({
4091
4350
  command: server.command,
4092
4351
  args: server.args,
4093
- env: toEnvRecord(server.env),
4352
+ env: {
4353
+ ...buildProxyEnv(),
4354
+ ...toEnvRecord(server.env)
4355
+ },
4094
4356
  cwd
4095
4357
  }),
4096
4358
  clientName: "fello-openai-compatible-agent",
@@ -4338,7 +4600,7 @@ Working style:
4338
4600
  File reading & editing strategy:
4339
4601
  - ReadFile will REJECT full reads of files over 100KB. Use line/limit to read specific sections, or set force=true if you genuinely need the full file content (rare).
4340
4602
  - Use the Search MCP's file_outline tool to preview file structure before reading (function/class/interface names with line ranges). Supports TypeScript, JavaScript, TSX, Python, Go, C, C++, Swift, Kotlin, Dart.
4341
- - Use the Search MCP's search tool (structured) or rg tool (raw args) to search file contents instead of reading entire files.
4603
+ - Use the Search MCP's grep tool (structured pattern search) or glob tool (file finder) to search file contents instead of reading entire files.
4342
4604
  - EditFile uses exact string matching (StrReplace style). Use unique surrounding code context in oldText to make matches precise. Set replaceAll=true when you intend to replace all occurrences.
4343
4605
  - You do NOT need to re-read a file after editing it \u2014 the changes are already saved.
4344
4606
 
@@ -4362,7 +4624,7 @@ import { tool as tool3 } from "ai";
4362
4624
  import { z as z6 } from "zod";
4363
4625
 
4364
4626
  // src/agents/image-tools.ts
4365
- import { resolve as resolve6 } from "path";
4627
+ import { resolve as resolve7 } from "path";
4366
4628
  import { readFile as readFile6 } from "fs/promises";
4367
4629
  import mime from "mime-types";
4368
4630
  import { tool as tool2, generateText } from "ai";
@@ -4399,7 +4661,7 @@ Provide a specific query describing what you want to know about the image \u2014
4399
4661
  });
4400
4662
  }
4401
4663
  try {
4402
- const absPath = resolve6(params.cwd, imgPath);
4664
+ const absPath = resolve7(params.cwd, imgPath);
4403
4665
  const buffer = await readFile6(absPath);
4404
4666
  const base64 = buffer.toString("base64");
4405
4667
  const mimeType = mime.lookup(absPath) || "image/png";
@@ -4754,7 +5016,6 @@ function buildWorkspaceSystemPrompt(cwd, additionalDirectories) {
4754
5016
  const workspacePrompt = `Current session working directory (cwd): ${cwd}.${extras} Use this as the default base path for relative paths.`;
4755
5017
  const now = /* @__PURE__ */ new Date();
4756
5018
  const dateStr = now.toLocaleDateString("en-CA");
4757
- const timeStr = now.toLocaleTimeString("en-US", { hour12: false });
4758
5019
  const weekday = now.toLocaleDateString("en-US", { weekday: "long" });
4759
5020
  const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
4760
5021
  const timezoneOffset = -now.getTimezoneOffset();
@@ -4763,7 +5024,7 @@ function buildWorkspaceSystemPrompt(cwd, additionalDirectories) {
4763
5024
  const offsetMinutes = String(Math.abs(timezoneOffset) % 60).padStart(2, "0");
4764
5025
  const utcOffset = `UTC${offsetSign}${offsetHours}:${offsetMinutes}`;
4765
5026
  const platform = process.platform;
4766
- const envContext = `Date and time: ${dateStr} ${timeStr} (${weekday})
5027
+ const envContext = `Date: ${dateStr} (${weekday})
4767
5028
  Timezone: ${timezone} (${utcOffset})
4768
5029
  Platform: ${platform}`;
4769
5030
  let prompt = `${BASE_SYSTEM_PROMPT}
@@ -5508,14 +5769,14 @@ function spawnOpenaiCompatibleApiAgent(options) {
5508
5769
  }
5509
5770
 
5510
5771
  // src/backend/agent/agent-terminal-manager.ts
5511
- import { spawn as spawn2, execFileSync as execFileSync2 } from "child_process";
5772
+ import { spawn as spawn2, execFileSync as execFileSync3 } from "child_process";
5512
5773
  import { randomBytes as randomBytes2 } from "crypto";
5513
5774
  function detectTerminalOutputEncoding() {
5514
5775
  if (process.platform !== "win32") {
5515
5776
  return "utf-8";
5516
5777
  }
5517
5778
  try {
5518
- const output = execFileSync2("cmd", ["/d", "/s", "/c", "chcp"], {
5779
+ const output = execFileSync3("cmd", ["/d", "/s", "/c", "chcp"], {
5519
5780
  encoding: "buffer",
5520
5781
  windowsHide: true
5521
5782
  });
@@ -5603,11 +5864,11 @@ var AgentTerminalManager = class {
5603
5864
  if (terminal.isFinished) {
5604
5865
  return { exitCode: terminal.exitCode, signal: terminal.signal };
5605
5866
  }
5606
- return new Promise((resolve8) => {
5867
+ return new Promise((resolve9) => {
5607
5868
  const originalOnExit = terminal.onExit;
5608
5869
  terminal.onExit = (code, signal) => {
5609
5870
  originalOnExit(code, signal);
5610
- resolve8({ exitCode: code, signal });
5871
+ resolve9({ exitCode: code, signal });
5611
5872
  };
5612
5873
  });
5613
5874
  }
@@ -5775,7 +6036,14 @@ var ACPBridge = class {
5775
6036
  }
5776
6037
  async connect() {
5777
6038
  const acpId = this.id;
5778
- const proc = this.options.agentInfo.type === "stdio" ? spawnStdioAgent({ ...this.options.agentInfo, cwd: this.options.cwd }) : this.options.agentInfo.provider === "openai-compatible" ? spawnOpenaiCompatibleApiAgent(this.options.agentInfo) : (() => {
6039
+ const proc = this.options.agentInfo.type === "stdio" ? spawnStdioAgent({
6040
+ ...this.options.agentInfo,
6041
+ cwd: this.options.cwd,
6042
+ env: {
6043
+ ...this.options.agentEnv,
6044
+ ...this.options.agentInfo.env
6045
+ }
6046
+ }) : this.options.agentInfo.provider === "openai-compatible" ? spawnOpenaiCompatibleApiAgent(this.options.agentInfo) : (() => {
5779
6047
  throw new Error(`Unsupported api provider: ${this.options.agentInfo.provider}`);
5780
6048
  })();
5781
6049
  this.process = proc;
@@ -5816,7 +6084,7 @@ var ACPBridge = class {
5816
6084
  const applyConfigOptions = this.applyConfigOptions.bind(this);
5817
6085
  const terminalManager = this.terminalManager;
5818
6086
  const sessionsCwdMap = this._sessionsCwdMap;
5819
- const clientApp = client({ name: "Fello" }).onRequest(methods3.client.session.requestPermission, (ctx) => {
6087
+ let clientApp = client({ name: "Fello" }).onRequest(methods3.client.session.requestPermission, (ctx) => {
5820
6088
  return onPermission(ctx.params);
5821
6089
  }).onNotification(methods3.client.session.update, (ctx) => {
5822
6090
  const params = ctx.params;
@@ -5859,25 +6127,12 @@ var ACPBridge = class {
5859
6127
  }).onRequest(methods3.client.terminal.release, (ctx) => {
5860
6128
  terminalManager.release(ctx.params.terminalId);
5861
6129
  return {};
5862
- }).onNotification(
5863
- "_kiro.dev/metadata",
5864
- (p) => p,
5865
- (ctx) => {
5866
- onExtNotification("_kiro.dev/metadata", ctx.params);
5867
- }
5868
- ).onNotification(
5869
- "_kiro.dev/commands/available",
5870
- (p) => p,
5871
- (ctx) => {
5872
- onExtNotification("_kiro.dev/commands/available", ctx.params);
5873
- }
5874
- ).onNotification(
5875
- "_kiro.dev/subagent/list_update",
5876
- (p) => p,
5877
- (ctx) => {
5878
- onExtNotification("_kiro.dev/subagent/list_update", ctx.params);
5879
- }
5880
- );
6130
+ });
6131
+ for (const spec of this.options.extNotificationSpecs) {
6132
+ clientApp = clientApp.onNotification(spec.method, spec.parse, (ctx) => {
6133
+ onExtNotification(spec.method, ctx.params);
6134
+ });
6135
+ }
5881
6136
  this.connection = clientApp.connect(stream);
5882
6137
  const initResult = await this.connection.agent.request(methods3.agent.initialize, {
5883
6138
  protocolVersion: PROTOCOL_VERSION2,
@@ -6103,7 +6358,9 @@ var ACPBridge = class {
6103
6358
  }
6104
6359
  async sendPrompt(params) {
6105
6360
  if (!this.connection) throw new Error("Not connected");
6106
- return this.connection.agent.request(methods3.agent.session.prompt, params);
6361
+ const res = await this.connection.agent.request(methods3.agent.session.prompt, params);
6362
+ this.options.onPromptCompleted?.(params.sessionId, res);
6363
+ return res;
6107
6364
  }
6108
6365
  async cancel(params) {
6109
6366
  if (!this.connection) return;
@@ -6139,6 +6396,378 @@ var ACPBridge = class {
6139
6396
  }
6140
6397
  };
6141
6398
 
6399
+ // src/backend/acp-adapters/acp-adapter.ts
6400
+ var AcpAdapter = class {
6401
+ /** Ext notification specs to register on the ACP client. */
6402
+ extNotificationSpecs = [];
6403
+ /**
6404
+ * Process an incoming notification.
6405
+ * - Return null to drop.
6406
+ * - Return [notification] to pass through (possibly transformed).
6407
+ * - Return [notification, ...synthetic] to pass through AND produce
6408
+ * additional notifications.
6409
+ *
6410
+ * Results go through the REST of the pipeline (title check, broadcast,
6411
+ * storage) — NOT through preprocessNotification again, so adapters
6412
+ * can safely inspect _meta fields without recursion risk. The original
6413
+ * notification (if included in results) is stored, which preserves
6414
+ * _meta for replay/state-rebuild.
6415
+ */
6416
+ preprocessNotification(notification, _currentSessionId, _agentId) {
6417
+ return [notification];
6418
+ }
6419
+ handleExtNotification(_method, _params, _currentSessionId, _agentId) {
6420
+ return [];
6421
+ }
6422
+ /**
6423
+ * Agent process env vars to inject when spawning the agent. Protocol-
6424
+ * specific environment needed by the agent process (e.g.
6425
+ * CODEBUDDY_DEFER_TOOL_LOADING for CodeBuddy). Aggregated by
6426
+ * adapters.ts and applied by ACPBridge when spawning a stdio agent;
6427
+ * agent-specific agentInfo.env still takes precedence.
6428
+ */
6429
+ getAgentEnv() {
6430
+ return {};
6431
+ }
6432
+ /**
6433
+ * Called by the bridge when a prompt round completes, with the full
6434
+ * PromptResponse in hand. Adapters that do turn-boundary / replay detection
6435
+ * override this to extract the agent's own protocol-clock timestamp and
6436
+ * freeze the boundary. Default no-op — only protocol-specific adapters
6437
+ * (e.g. CodeBuddy, which stamps PromptResponse._meta with
6438
+ * codebuddy.ai/requestId + timestamp) need it; generic adapters have no
6439
+ * protocol timestamp to work from.
6440
+ */
6441
+ handlePromptCompleted(_sessionId, _res) {
6442
+ }
6443
+ // ── State lifecycle (default no-ops) ───────────────────────────────
6444
+ rekey(_oldKey, _newKey) {
6445
+ }
6446
+ cleanup(_sessionKey) {
6447
+ }
6448
+ clearAll() {
6449
+ }
6450
+ };
6451
+
6452
+ // src/backend/acp-adapters/codebuddy-adapter.ts
6453
+ var CODEBUDDY_STATUS_MAP = {
6454
+ running: "in_progress",
6455
+ completed: "completed",
6456
+ idle: "in_progress",
6457
+ pending: "pending",
6458
+ failed: "failed"
6459
+ };
6460
+ var CodebuddyAdapter = class extends AcpAdapter {
6461
+ stateMap = /* @__PURE__ */ new Map();
6462
+ /**
6463
+ * Per-session turn-boundary timestamp (epoch ms, from the agent's own
6464
+ * protocol clock). Frozen when a prompt completes (via handlePromptCompleted),
6465
+ * so content chunks emitted afterwards with an earlier protocol timestamp
6466
+ * are previous-turn replays. Only CodeBuddy stamps PromptResponse._meta
6467
+ * with a protocol timestamp, so this stays here rather than in the base.
6468
+ */
6469
+ turnBoundaryTs = /* @__PURE__ */ new Map();
6470
+ /**
6471
+ * CodeBuddy spawn env.
6472
+ */
6473
+ getAgentEnv() {
6474
+ return {
6475
+ CODEBUDDY_DEFER_TOOL_LOADING: "0",
6476
+ CODEBUDDY_DISABLE_AUTO_MEMORY: "1"
6477
+ };
6478
+ }
6479
+ /**
6480
+ * Freeze the turn-boundary on prompt completion. Only CodeBuddy stamps the
6481
+ * PromptResponse._meta with codebuddy.ai/requestId + a protocol timestamp,
6482
+ * so this stays here rather than in the generic bridge — the agent's own
6483
+ * clock is the boundary used to drop replayed prior-turn chunks (avoids
6484
+ * timezone / clock-skew issues that wall-clock Date.now() would introduce).
6485
+ */
6486
+ handlePromptCompleted(sessionId, res) {
6487
+ const meta = res._meta;
6488
+ if (meta && typeof meta["codebuddy.ai/requestId"] === "string") {
6489
+ const ts = Date.parse(typeof meta["timestamp"] === "string" ? meta["timestamp"] : "");
6490
+ if (!isNaN(ts)) this.turnBoundaryTs.set(sessionId, ts);
6491
+ }
6492
+ }
6493
+ /**
6494
+ * One unified hook for all notification processing:
6495
+ *
6496
+ * 1. Replay detection — the adapter freezes a turn-boundary timestamp in
6497
+ * handlePromptCompleted() when a prompt completes (using the agent's own
6498
+ * protocol clock). Drop agent_message_chunk / agent_thought_chunk whose
6499
+ * _meta.timestamp is earlier than that boundary: CodeBuddy re-broadcasts
6500
+ * the previous turn's messages when a new prompt begins, and those
6501
+ * re-emitted chunks carry the previous turn's (earlier) timestamps. Only
6502
+ * applies to chunks that carry codebuddy.ai/requestId.
6503
+ * 2. memberEvent chunk routing — rewrite notification.sessionId from
6504
+ * parent to member sessionId (CodeBuddy stamps all member chunks
6505
+ * with the parent session).
6506
+ * 3. Drop teammate-directed user_message_chunks (task assignments from
6507
+ * team-lead to members, wrapped in <teammate-message>).
6508
+ * 4. teamUpdate lifecycle — convert team_created / member_status_change /
6509
+ * team_deleted into AddonSessionUpdate broadcasts via _meta.fello.update.
6510
+ *
6511
+ * Returns null to drop, [notification] to pass through, or
6512
+ * [notification, ...synthetic] to pass through + produce additional.
6513
+ * Results go through the REST of the pipeline (not this method again).
6514
+ */
6515
+ preprocessNotification(notification, currentSessionId, agentId) {
6516
+ const meta = notification.update?._meta;
6517
+ const sessionUpdate = notification.update?.sessionUpdate;
6518
+ const requestId = meta?.["codebuddy.ai/requestId"];
6519
+ const metaTimestamp = meta?.["timestamp"];
6520
+ if (typeof requestId === "string" && typeof metaTimestamp === "string" && (sessionUpdate === "agent_message_chunk" || sessionUpdate === "agent_thought_chunk")) {
6521
+ const ts = Date.parse(metaTimestamp);
6522
+ if (!isNaN(ts)) {
6523
+ const boundary = this.turnBoundaryTs.get(currentSessionId);
6524
+ if (boundary !== void 0 && ts < boundary) {
6525
+ return null;
6526
+ }
6527
+ }
6528
+ }
6529
+ const memberEvent = meta?.["codebuddy.ai/memberEvent"];
6530
+ if (sessionUpdate === "user_message_chunk" && typeof memberEvent === "string") {
6531
+ return null;
6532
+ }
6533
+ let result = notification;
6534
+ if (typeof memberEvent === "string") {
6535
+ const state = this.stateMap.get(currentSessionId);
6536
+ const memberSessionId = state?.members.get(memberEvent)?.sessionId;
6537
+ if (memberSessionId && notification.sessionId !== memberSessionId) {
6538
+ result = { ...notification, sessionId: memberSessionId };
6539
+ }
6540
+ }
6541
+ const teamUpdate = meta?.["codebuddy.ai/teamUpdate"];
6542
+ if (teamUpdate && typeof teamUpdate === "object") {
6543
+ const synthetic = this.processTeamUpdate(
6544
+ teamUpdate,
6545
+ currentSessionId,
6546
+ agentId
6547
+ );
6548
+ return synthetic.length > 0 ? [result, ...synthetic] : [result];
6549
+ }
6550
+ return [result];
6551
+ }
6552
+ // ── Team update processing ─────────────────────────────────────────
6553
+ /**
6554
+ * Process a codebuddy.ai/teamUpdate event. Updates the cached team
6555
+ * state and produces synthetic subagent_update notifications.
6556
+ *
6557
+ * - team_created → cache teamName as activeTeamName (no notifications)
6558
+ * - member_status_change → resolve each member's teamName via event-level
6559
+ * teamName / existing member's teamName / activeTeamName, then produce
6560
+ * a subagent_update notification per member
6561
+ * - team_deleted → mark still-active members of THAT team as `failed`
6562
+ * (preserving completed/failed), then produce a notification per active
6563
+ * member. Only removes that team's members from the cache.
6564
+ * - team_idle / others → no-op
6565
+ */
6566
+ processTeamUpdate(teamUpdate, currentSessionId, agentId) {
6567
+ const type = typeof teamUpdate.type === "string" ? teamUpdate.type : "";
6568
+ const eventTeamName = typeof teamUpdate.teamName === "string" ? teamUpdate.teamName : null;
6569
+ const getOrCreateState = () => {
6570
+ let s = this.stateMap.get(currentSessionId);
6571
+ if (!s) {
6572
+ s = { members: /* @__PURE__ */ new Map(), activeTeamName: null };
6573
+ this.stateMap.set(currentSessionId, s);
6574
+ }
6575
+ return s;
6576
+ };
6577
+ const makeSubagentUpdate = (memberSessionId, memberName, prompt, status) => {
6578
+ const update = {
6579
+ sessionUpdate: "subagent_update",
6580
+ sessionId: memberSessionId,
6581
+ ...memberName !== void 0 && { name: memberName },
6582
+ ...prompt !== void 0 && { prompt },
6583
+ status
6584
+ };
6585
+ return {
6586
+ sessionId: currentSessionId.replace(`${agentId}:`, ""),
6587
+ update: {
6588
+ sessionUpdate: "session_info_update",
6589
+ _meta: { fello: { update } }
6590
+ }
6591
+ };
6592
+ };
6593
+ if (type === "team_created") {
6594
+ const state = getOrCreateState();
6595
+ if (eventTeamName) state.activeTeamName = eventTeamName;
6596
+ return [];
6597
+ }
6598
+ if (type === "team_deleted") {
6599
+ const state = this.stateMap.get(currentSessionId);
6600
+ if (!state || !eventTeamName) return [];
6601
+ const results = [];
6602
+ for (const [memberName, member] of state.members) {
6603
+ if (member.teamName !== eventTeamName) continue;
6604
+ if (member.status !== "completed" && member.status !== "failed") {
6605
+ results.push(makeSubagentUpdate(member.sessionId, void 0, void 0, "failed"));
6606
+ }
6607
+ state.members.delete(memberName);
6608
+ }
6609
+ if (state.activeTeamName === eventTeamName) {
6610
+ state.activeTeamName = null;
6611
+ }
6612
+ return results;
6613
+ }
6614
+ if (type === "member_status_change") {
6615
+ const state = getOrCreateState();
6616
+ const members = Array.isArray(teamUpdate.members) ? teamUpdate.members : [];
6617
+ const results = [];
6618
+ for (const member of members) {
6619
+ if (!member || typeof member !== "object") continue;
6620
+ const m = member;
6621
+ const memberName = typeof m.name === "string" ? m.name : null;
6622
+ const memberSessionId = typeof m.sessionId === "string" ? m.sessionId : null;
6623
+ if (!memberName || !memberSessionId) continue;
6624
+ const status = typeof m.status === "string" ? CODEBUDDY_STATUS_MAP[m.status] ?? "in_progress" : "in_progress";
6625
+ const existing = state.members.get(memberName);
6626
+ const resolvedTeamName = eventTeamName ?? existing?.teamName ?? state.activeTeamName ?? "";
6627
+ state.members.set(memberName, {
6628
+ sessionId: memberSessionId,
6629
+ status,
6630
+ teamName: resolvedTeamName
6631
+ });
6632
+ const prompt = typeof m.description === "string" ? m.description : void 0;
6633
+ results.push(makeSubagentUpdate(memberSessionId, memberName, prompt, status));
6634
+ }
6635
+ return results;
6636
+ }
6637
+ return [];
6638
+ }
6639
+ // ── State lifecycle (mirror bridge-connect) ────────────────────────
6640
+ rekey(oldKey, newKey) {
6641
+ const state = this.stateMap.get(oldKey);
6642
+ if (state) {
6643
+ this.stateMap.delete(oldKey);
6644
+ this.stateMap.set(newKey, state);
6645
+ }
6646
+ const boundary = this.turnBoundaryTs.get(oldKey);
6647
+ if (boundary !== void 0) {
6648
+ this.turnBoundaryTs.delete(oldKey);
6649
+ this.turnBoundaryTs.set(newKey, boundary);
6650
+ }
6651
+ }
6652
+ cleanup(sessionKey) {
6653
+ this.stateMap.delete(sessionKey);
6654
+ this.turnBoundaryTs.delete(sessionKey);
6655
+ }
6656
+ clearAll() {
6657
+ this.stateMap.clear();
6658
+ this.turnBoundaryTs.clear();
6659
+ }
6660
+ };
6661
+
6662
+ // src/backend/acp-adapters/kiro-adapter.ts
6663
+ var KIRO_STATUS_MAP = {
6664
+ pending: "pending",
6665
+ working: "in_progress",
6666
+ terminated: "completed",
6667
+ failed: "failed"
6668
+ };
6669
+ var parseMetadata = (p) => p;
6670
+ var parseCommandsAvailable = (p) => p;
6671
+ var parseSubagentList = (p) => p;
6672
+ var KiroAdapter = class extends AcpAdapter {
6673
+ /** Ext notification specs declared here, registered by ACPBridge. */
6674
+ extNotificationSpecs = [
6675
+ { method: "_kiro.dev/metadata", parse: parseMetadata },
6676
+ { method: "_kiro.dev/commands/available", parse: parseCommandsAvailable },
6677
+ { method: "_kiro.dev/subagent/list_update", parse: parseSubagentList }
6678
+ ];
6679
+ /**
6680
+ * Translate a Kiro ext notification into synthetic SessionNotification(s).
6681
+ * Returns an empty array if the method is unrecognized.
6682
+ */
6683
+ handleExtNotification(method, params, currentSessionId, agentId) {
6684
+ switch (method) {
6685
+ case "_kiro.dev/metadata":
6686
+ return this.handleMetadata(params, currentSessionId, agentId);
6687
+ case "_kiro.dev/commands/available":
6688
+ return this.handleCommandsAvailable(params, currentSessionId, agentId);
6689
+ case "_kiro.dev/subagent/list_update":
6690
+ return this.handleSubagentListUpdate(params, currentSessionId, agentId);
6691
+ default:
6692
+ return [];
6693
+ }
6694
+ }
6695
+ // ── Handlers ──────────────────────────────────────────────────────
6696
+ handleMetadata(params, currentSessionId, agentId) {
6697
+ if (typeof params === "object" && params && "sessionId" in params && typeof params.sessionId === "string" && "contextUsagePercentage" in params && typeof params.contextUsagePercentage === "number" && currentSessionId === `${agentId}:${params.sessionId}`) {
6698
+ return [
6699
+ {
6700
+ sessionId: params.sessionId,
6701
+ update: {
6702
+ sessionUpdate: "usage_update",
6703
+ used: params.contextUsagePercentage / 100,
6704
+ size: 1
6705
+ }
6706
+ }
6707
+ ];
6708
+ }
6709
+ return [];
6710
+ }
6711
+ handleCommandsAvailable(params, currentSessionId, agentId) {
6712
+ if (typeof params === "object" && params && "sessionId" in params && typeof params.sessionId === "string" && "commands" in params && Array.isArray(params.commands) && currentSessionId === `${agentId}:${params.sessionId}`) {
6713
+ const commands = [];
6714
+ for (const item of params.commands) {
6715
+ if (typeof item === "object" && item && "name" in item && typeof item.name === "string") {
6716
+ commands.push({
6717
+ name: item.name.replace(/^\//, ""),
6718
+ description: item.description ? String(item.description) : ""
6719
+ });
6720
+ }
6721
+ }
6722
+ return [
6723
+ {
6724
+ sessionId: params.sessionId,
6725
+ update: {
6726
+ sessionUpdate: "available_commands_update",
6727
+ availableCommands: commands
6728
+ }
6729
+ }
6730
+ ];
6731
+ }
6732
+ return [];
6733
+ }
6734
+ handleSubagentListUpdate(params, currentSessionId, agentId) {
6735
+ if (typeof params === "object" && params && currentSessionId && "subagents" in params && Array.isArray(params.subagents)) {
6736
+ const results = [];
6737
+ for (const subagent of params.subagents) {
6738
+ if (typeof subagent === "object" && subagent && "sessionId" in subagent && typeof subagent.sessionId === "string") {
6739
+ const update = {
6740
+ sessionUpdate: "subagent_update",
6741
+ sessionId: subagent.sessionId,
6742
+ name: typeof subagent.sessionName === "string" ? subagent.sessionName : void 0,
6743
+ prompt: typeof subagent.initialQuery === "string" ? subagent.initialQuery : void 0,
6744
+ status: KIRO_STATUS_MAP[String(subagent?.status?.type)]
6745
+ };
6746
+ results.push({
6747
+ sessionId: currentSessionId.replace(`${agentId}:`, ""),
6748
+ update: {
6749
+ sessionUpdate: "session_info_update",
6750
+ _meta: { fello: { update } }
6751
+ }
6752
+ });
6753
+ }
6754
+ }
6755
+ return results;
6756
+ }
6757
+ return [];
6758
+ }
6759
+ };
6760
+
6761
+ // src/backend/acp-adapters/adapters.ts
6762
+ var codebuddyAdapter = new CodebuddyAdapter();
6763
+ var kiroAdapter = new KiroAdapter();
6764
+ var adapters = [codebuddyAdapter, kiroAdapter];
6765
+ var extNotificationSpecs = adapters.flatMap((a) => a.extNotificationSpecs);
6766
+ var agentEnv = Object.assign(
6767
+ {},
6768
+ ...adapters.map((a) => a.getAgentEnv())
6769
+ );
6770
+
6142
6771
  // src/backend/agent/resolve-agent-info.ts
6143
6772
  function resolveAgentInfo(agentId) {
6144
6773
  const settings = storageOps.getSettings();
@@ -6200,10 +6829,59 @@ function createBridgeConnectModule(ctx, deps) {
6200
6829
  }
6201
6830
  sessionAgentMap.set(sessionKey, agentId);
6202
6831
  let currentSessionId = null;
6832
+ function processSessionUpdate(notification) {
6833
+ let results = [notification];
6834
+ if (currentSessionId) {
6835
+ for (const adapter of adapters) {
6836
+ const next = [];
6837
+ for (const n of results) {
6838
+ const processed = adapter.preprocessNotification(n, currentSessionId, agentId);
6839
+ if (processed !== null) {
6840
+ next.push(...processed);
6841
+ }
6842
+ }
6843
+ results = next;
6844
+ }
6845
+ }
6846
+ if (results.length === 0) return;
6847
+ if (!currentSessionId) return;
6848
+ for (const result of results) {
6849
+ const sessionUpdate = result.update?.sessionUpdate;
6850
+ if (currentSessionId && currentSessionId === `${agentId}:${result.sessionId}`) {
6851
+ if (sessionUpdate === "session_info_update") {
6852
+ if (result.update.title) {
6853
+ storage.updateSession(currentSessionId, { title: result.update.title });
6854
+ const updated = storage.getSession(currentSessionId);
6855
+ if (updated) sendEvent("session-changed", { session: updated });
6856
+ }
6857
+ }
6858
+ if (sessionUpdate === "usage_update") {
6859
+ publishUsage(currentSessionId, result.update);
6860
+ continue;
6861
+ }
6862
+ if (sessionUpdate === "available_commands_update") {
6863
+ publishAvailableCommands(currentSessionId, result.update.availableCommands ?? []);
6864
+ continue;
6865
+ }
6866
+ if (sessionUpdate === "current_mode_update") {
6867
+ const session = storage.getSession(currentSessionId);
6868
+ if (session && session.modes) {
6869
+ session.modes.currentModeId = result.update.currentModeId ?? null;
6870
+ storage.updateSession(currentSessionId, { modes: session.modes });
6871
+ const updated = storage.getSession(currentSessionId);
6872
+ if (updated) sendEvent("session-changed", { session: updated });
6873
+ }
6874
+ }
6875
+ }
6876
+ broadcastAndSaveSessionUpdate(currentSessionId, result);
6877
+ }
6878
+ }
6203
6879
  const agentInfo = resolveAgentInfo(agentId);
6204
6880
  const bridge = new ACPBridge(agentId, {
6205
6881
  agentInfo,
6206
6882
  cwd,
6883
+ extNotificationSpecs,
6884
+ agentEnv,
6207
6885
  onSessionConnect: (connection) => {
6208
6886
  currentSessionId = `${agentId}:${connection.sessionId}`;
6209
6887
  storage.updateSession(currentSessionId, { connectionStatus: "connected" }, false);
@@ -6211,96 +6889,17 @@ function createBridgeConnectModule(ctx, deps) {
6211
6889
  if (updated) sendEvent("session-changed", { session: updated });
6212
6890
  },
6213
6891
  onSessionUpdate: (notification) => {
6214
- const sessionUpdate = notification.update?.sessionUpdate;
6215
- if (currentSessionId) {
6216
- if (currentSessionId === `${agentId}:${notification.sessionId}`) {
6217
- if (sessionUpdate === "session_info_update") {
6218
- if (notification.update.title) {
6219
- storage.updateSession(currentSessionId, { title: notification.update.title });
6220
- const updated = storage.getSession(currentSessionId);
6221
- if (updated) sendEvent("session-changed", { session: updated });
6222
- }
6223
- }
6224
- if (sessionUpdate === "usage_update") {
6225
- publishUsage(currentSessionId, notification.update);
6226
- return;
6227
- }
6228
- if (sessionUpdate === "available_commands_update") {
6229
- publishAvailableCommands(
6230
- currentSessionId,
6231
- notification.update.availableCommands ?? []
6232
- );
6233
- return;
6234
- }
6235
- if (sessionUpdate === "current_mode_update") {
6236
- const session = storage.getSession(currentSessionId);
6237
- if (session && session.modes) {
6238
- session.modes.currentModeId = notification.update.currentModeId ?? null;
6239
- storage.updateSession(currentSessionId, { modes: session.modes });
6240
- const updated = storage.getSession(currentSessionId);
6241
- if (updated) sendEvent("session-changed", { session: updated });
6242
- }
6243
- }
6244
- }
6245
- broadcastAndSaveSessionUpdate(currentSessionId, notification);
6246
- }
6892
+ processSessionUpdate(notification);
6247
6893
  },
6248
6894
  onExtNotification: (method, params) => {
6249
- if (method === "_kiro.dev/metadata") {
6250
- if (typeof params === "object" && params && "sessionId" in params && typeof params.sessionId === "string" && "contextUsagePercentage" in params && typeof params.contextUsagePercentage === "number" && currentSessionId === `${agentId}:${params.sessionId}`) {
6251
- publishUsage(currentSessionId, {
6252
- used: params.contextUsagePercentage / 100,
6253
- size: 1
6254
- });
6255
- }
6256
- return;
6257
- }
6258
- if (method === "_kiro.dev/commands/available") {
6259
- if (typeof params === "object" && params && "sessionId" in params && typeof params.sessionId === "string" && "commands" in params && Array.isArray(params.commands) && currentSessionId === `${agentId}:${params.sessionId}`) {
6260
- const commands = [];
6261
- for (const item of params.commands) {
6262
- if (typeof item === "object" && item && "name" in item && typeof item.name === "string") {
6263
- commands.push({
6264
- name: item.name.replace(/^\//, ""),
6265
- description: item.description ? String(item.description) : ""
6266
- });
6267
- }
6268
- }
6269
- publishAvailableCommands(currentSessionId, commands);
6270
- }
6271
- return;
6272
- }
6273
- if (method === "_kiro.dev/subagent/list_update") {
6274
- if (typeof params === "object" && params && currentSessionId && "subagents" in params && Array.isArray(params.subagents)) {
6275
- for (const subagent of params.subagents) {
6276
- if (typeof subagent === "object" && subagent && "sessionId" in subagent && typeof subagent.sessionId === "string") {
6277
- const update = {
6278
- sessionUpdate: "subagent_update",
6279
- sessionId: subagent.sessionId,
6280
- name: typeof subagent.sessionName === "string" ? subagent.sessionName : void 0,
6281
- prompt: typeof subagent.initialQuery === "string" ? subagent.initialQuery : void 0,
6282
- status: {
6283
- pending: "pending",
6284
- working: "in_progress",
6285
- terminated: "completed",
6286
- failed: "failed"
6287
- }[String(subagent?.status?.type)]
6288
- };
6289
- broadcastAndSaveSessionUpdate(currentSessionId, {
6290
- sessionId: currentSessionId.replace(`${agentId}:`, ""),
6291
- update: {
6292
- sessionUpdate: "session_info_update",
6293
- _meta: {
6294
- fello: {
6295
- update
6296
- }
6297
- }
6298
- }
6299
- });
6300
- }
6895
+ for (const adapter of adapters) {
6896
+ const results = adapter.handleExtNotification(method, params, currentSessionId, agentId);
6897
+ if (results.length > 0) {
6898
+ for (const result of results) {
6899
+ processSessionUpdate(result);
6301
6900
  }
6901
+ return;
6302
6902
  }
6303
- return;
6304
6903
  }
6305
6904
  },
6306
6905
  onPermissionRequest: async (request) => {
@@ -6357,6 +6956,13 @@ function createBridgeConnectModule(ctx, deps) {
6357
6956
  console.error("write terminal output error: ", { sessionId, terminalId, err });
6358
6957
  }
6359
6958
  sendEvent("agent-terminal-output", { sessionId, terminalId, data });
6959
+ },
6960
+ // On prompt completion, hand the full PromptResponse to each adapter so
6961
+ // it can freeze its own turn-boundary (CodeBuddy extracts its protocol
6962
+ // timestamp; other adapters are no-ops).
6963
+ onPromptCompleted: (sessionId, res) => {
6964
+ const key = `${agentId}:${sessionId}`;
6965
+ for (const a of adapters) a.handlePromptCompleted(key, res);
6360
6966
  }
6361
6967
  });
6362
6968
  let newConnectPromise;
@@ -6382,12 +6988,14 @@ function createBridgeConnectModule(ctx, deps) {
6382
6988
  sessionAgentMap.delete(oldKey);
6383
6989
  sessionAgentMap.set(newKey, agentId);
6384
6990
  }
6991
+ for (const a of adapters) a.rekey(oldKey, newKey);
6385
6992
  }
6386
6993
  async function killBridge(sessionKey) {
6387
6994
  const p = bridges.get(sessionKey);
6388
6995
  if (p) {
6389
6996
  bridges.delete(sessionKey);
6390
6997
  sessionAgentMap.delete(sessionKey);
6998
+ for (const a of adapters) a.cleanup(sessionKey);
6391
6999
  try {
6392
7000
  const b = await p;
6393
7001
  await b.kill();
@@ -6417,6 +7025,7 @@ function createBridgeConnectModule(ctx, deps) {
6417
7025
  }
6418
7026
  bridges.clear();
6419
7027
  sessionAgentMap.clear();
7028
+ for (const a of adapters) a.clearAll();
6420
7029
  await Promise.all(killPromises);
6421
7030
  }
6422
7031
  return {
@@ -6677,10 +7286,109 @@ import {
6677
7286
  copyFile
6678
7287
  } from "fs/promises";
6679
7288
  import * as mimeTypes4 from "mime-types";
6680
- import { dirname as dirname6, join as join17, relative as relative7, extname as extname2, basename as basename3 } from "path";
7289
+ import { dirname as dirname7, join as join17, relative as relative9, extname as extname2, basename as basename3 } from "path";
7290
+
7291
+ // src/backend/project/git-utils.ts
7292
+ import { execFile, spawn as spawn3 } from "child_process";
7293
+ import { dirname as dirname6, relative as relative8 } from "path";
7294
+ import { promisify } from "util";
7295
+ var execFileAsync = promisify(execFile);
7296
+ async function getGitIgnoredPaths(cwd, relPaths) {
7297
+ if (relPaths.length === 0) return /* @__PURE__ */ new Set();
7298
+ return new Promise((resolve9) => {
7299
+ const child = spawn3("git", ["check-ignore", "-z", "--stdin"], {
7300
+ cwd,
7301
+ timeout: 3e3,
7302
+ // spawn defaults windowsHide to false; without this, every readDir
7303
+ // would flash a console window on Windows.
7304
+ windowsHide: true
7305
+ });
7306
+ const chunks = [];
7307
+ child.stdout.on("data", (chunk) => chunks.push(chunk));
7308
+ child.on("error", () => resolve9(/* @__PURE__ */ new Set()));
7309
+ child.on("close", () => {
7310
+ const ignored = /* @__PURE__ */ new Set();
7311
+ for (const p of Buffer.concat(chunks).toString("utf8").split("\0")) {
7312
+ if (p) ignored.add(toPosixPath(p));
7313
+ }
7314
+ resolve9(ignored);
7315
+ });
7316
+ try {
7317
+ child.stdin.write(relPaths.join("\0") + "\0");
7318
+ child.stdin.end();
7319
+ } catch {
7320
+ resolve9(/* @__PURE__ */ new Set());
7321
+ }
7322
+ });
7323
+ }
7324
+ async function getGitStatus(cwd) {
7325
+ try {
7326
+ const { stdout } = await execFileAsync("git", ["status", "--porcelain", "-b", "-z"], {
7327
+ cwd,
7328
+ timeout: 2e3,
7329
+ maxBuffer: 10 * 1024 * 1024
7330
+ });
7331
+ const lines = stdout.split("\0").filter(Boolean);
7332
+ if (lines.length === 0) return null;
7333
+ let branchLine = lines[0];
7334
+ let branch = "";
7335
+ if (branchLine.startsWith("## ")) {
7336
+ branchLine = branchLine.slice(3);
7337
+ if (branchLine.startsWith("No commits yet on "))
7338
+ branch = branchLine.slice("No commits yet on ".length);
7339
+ else if (branchLine.startsWith("HEAD (no branch)")) branch = "HEAD";
7340
+ else branch = branchLine.split("...")[0];
7341
+ }
7342
+ const files = {};
7343
+ for (let i = 1; i < lines.length; i++) {
7344
+ const line = lines[i];
7345
+ const status = line.slice(0, 2);
7346
+ if (line.length < 4) continue;
7347
+ let path2 = line.slice(3);
7348
+ if ((status.includes("R") || status.includes("C")) && i + 1 < lines.length) {
7349
+ path2 = lines[i + 1];
7350
+ i++;
7351
+ }
7352
+ files[toPosixPath(path2)] = status;
7353
+ }
7354
+ return { branch, files };
7355
+ } catch {
7356
+ return null;
7357
+ }
7358
+ }
7359
+ async function readGitHeadFile(targetPath, encoding) {
7360
+ try {
7361
+ const cwd = dirname6(targetPath);
7362
+ const relPath = relative8(cwd, targetPath);
7363
+ const { stdout } = await execFileAsync("git", ["show", `HEAD:./${relPath}`], {
7364
+ cwd,
7365
+ maxBuffer: 10 * 1024 * 1024,
7366
+ encoding: encoding ?? "utf8"
7367
+ });
7368
+ return stdout;
7369
+ } catch {
7370
+ return "";
7371
+ }
7372
+ }
7373
+
7374
+ // src/backend/project/filesystem.ts
6681
7375
  var SEARCH_MAX_RESULTS = 10;
6682
7376
  var SEARCH_FUSE_THRESHOLD = 0.4;
6683
7377
  var SEARCH_CACHE_TTL_MS = 6e4;
7378
+ var IGNORE_NAME_SET = /* @__PURE__ */ new Set([".git", ".svn", ".hg"]);
7379
+ var SEARCH_IGNORE_NAME_SET = /* @__PURE__ */ new Set(["node_modules", "vendor", "__pycache__"]);
7380
+ function hasForbiddenSegment(fullPath, cwd, ...nameSets) {
7381
+ if (fullPath === cwd) return false;
7382
+ const relPath = relative9(cwd, fullPath);
7383
+ if (!relPath) return false;
7384
+ const segments = relPath.split(/[\\/]+/);
7385
+ for (let i = 0; i < segments.length; i++) {
7386
+ const name = segments[i];
7387
+ if (!name || name === ".") continue;
7388
+ if (nameSets.some((set) => set.has(name))) return true;
7389
+ }
7390
+ return false;
7391
+ }
6684
7392
  function createFilesystemState(ctx) {
6685
7393
  const { storage } = ctx;
6686
7394
  const projectFsVersions = /* @__PURE__ */ new Map();
@@ -6713,9 +7421,9 @@ function createFilesystemState(ctx) {
6713
7421
  const full = join17(dir, name);
6714
7422
  const s = await stat4(full).catch(() => null);
6715
7423
  if (!s) continue;
6716
- if (isIgnorePath(full, cwd)) continue;
7424
+ if (hasForbiddenSegment(full, cwd, IGNORE_NAME_SET, SEARCH_IGNORE_NAME_SET)) continue;
6717
7425
  if (fileScene.has(full)) continue;
6718
- const rel = relative7(cwd, full);
7426
+ const rel = relative9(cwd, full);
6719
7427
  const posixRel = toPosixPath(rel);
6720
7428
  allFiles.push({ id: posixRel, filename: rel, isFolder: s.isDirectory() });
6721
7429
  if (s.isDirectory()) await collect(full);
@@ -6727,12 +7435,12 @@ function createFilesystemState(ctx) {
6727
7435
  async function getSystemFilePath({
6728
7436
  projectId,
6729
7437
  path: inputPath,
6730
- isAbsolute: isAbsolute6
7438
+ isAbsolute: isAbsolute8
6731
7439
  }) {
6732
7440
  const project = storage.getProject(projectId);
6733
7441
  if (!project) throw new Error("Project not found");
6734
- if (isAbsolute6) return resolveSafePath(project.cwd, inputPath);
6735
- return relative7(project.cwd, resolveSafePath(project.cwd, inputPath));
7442
+ if (isAbsolute8) return resolveSafePath(project.cwd, inputPath);
7443
+ return relative9(project.cwd, resolveSafePath(project.cwd, inputPath));
6736
7444
  }
6737
7445
  async function copyFileToWorkspace({
6738
7446
  projectId,
@@ -6755,7 +7463,7 @@ function createFilesystemState(ctx) {
6755
7463
  }
6756
7464
  await copyFile(sourcePath, destPath);
6757
7465
  markProjectFsDirty(projectId);
6758
- return { success: true, destPath: toPosixPath(relative7(cwd, destPath)) };
7466
+ return { success: true, destPath: toPosixPath(relative9(cwd, destPath)) };
6759
7467
  }
6760
7468
  async function readUrlAsDataUrl({ url: inputUrl, mimeType }) {
6761
7469
  const MAX_FILE_SIZE = 20 * 1024 * 1024;
@@ -6805,12 +7513,12 @@ function createFilesystemState(ctx) {
6805
7513
  const results = [];
6806
7514
  for (const name of entries) {
6807
7515
  const full = join17(cwd, name);
6808
- if (isIgnorePath(full, cwd)) continue;
7516
+ if (hasForbiddenSegment(full, cwd, IGNORE_NAME_SET, SEARCH_IGNORE_NAME_SET)) continue;
6809
7517
  if (fileScene.has(full)) continue;
6810
7518
  fileScene.add(full);
6811
7519
  const s = await stat4(full).catch(() => null);
6812
7520
  if (!s) continue;
6813
- const rel = relative7(cwd, full);
7521
+ const rel = relative9(cwd, full);
6814
7522
  results.push({ id: toPosixPath(rel), filename: rel, isFolder: s.isDirectory() });
6815
7523
  if (results.length >= SEARCH_MAX_RESULTS) break;
6816
7524
  }
@@ -6849,14 +7557,23 @@ function createFilesystemState(ctx) {
6849
7557
  const full = join17(startPath, name);
6850
7558
  const s = await stat4(full).catch(() => null);
6851
7559
  if (!s) continue;
6852
- if (isIgnorePath(full, cwd)) continue;
6853
- const relId = toPosixPath(relative7(cwd, full));
6854
- results.push({ id: relId, name, isFolder: s.isDirectory() });
7560
+ if (hasForbiddenSegment(full, cwd, IGNORE_NAME_SET)) continue;
7561
+ const relId = toPosixPath(relative9(cwd, full));
7562
+ results.push({ id: relId, name, isFolder: s.isDirectory(), ignored: false });
6855
7563
  }
6856
7564
  results.sort((a, b) => {
6857
7565
  if (a.isFolder !== b.isFolder) return a.isFolder ? -1 : 1;
6858
7566
  return a.name.localeCompare(b.name);
6859
7567
  });
7568
+ const ignoredPaths = await getGitIgnoredPaths(
7569
+ cwd,
7570
+ results.map((r) => r.id)
7571
+ );
7572
+ if (ignoredPaths.size > 0) {
7573
+ for (const r of results) {
7574
+ if (ignoredPaths.has(r.id)) r.ignored = true;
7575
+ }
7576
+ }
6860
7577
  return results;
6861
7578
  }
6862
7579
  async function createFile({
@@ -6870,7 +7587,7 @@ function createFilesystemState(ctx) {
6870
7587
  if (isFolder) {
6871
7588
  await mkdir(targetPath, { recursive: true });
6872
7589
  } else {
6873
- await mkdir(dirname6(targetPath), { recursive: true });
7590
+ await mkdir(dirname7(targetPath), { recursive: true });
6874
7591
  await writeFile3(targetPath, "");
6875
7592
  }
6876
7593
  markProjectFsDirty(projectId);
@@ -6977,6 +7694,22 @@ function createFilesystemState(ctx) {
6977
7694
  await writeFile3(currentDest, buffer);
6978
7695
  markProjectFsDirty(projectId);
6979
7696
  }
7697
+ async function getGitStatus2({ projectId, cwd }) {
7698
+ const project = storage.getProject(projectId);
7699
+ if (!project) return null;
7700
+ const targetCwd = cwd ? resolveSafePath(project.cwd, cwd) : project.cwd;
7701
+ return getGitStatus(targetCwd);
7702
+ }
7703
+ async function readGitHeadFile2({
7704
+ projectId,
7705
+ relativePath,
7706
+ encoding
7707
+ }) {
7708
+ const project = storage.getProject(projectId);
7709
+ if (!project) return "";
7710
+ const targetPath = resolveSafePath(project.cwd, relativePath);
7711
+ return readGitHeadFile(targetPath, encoding);
7712
+ }
6980
7713
  async function getPlatform() {
6981
7714
  return process.platform;
6982
7715
  }
@@ -6996,83 +7729,16 @@ function createFilesystemState(ctx) {
6996
7729
  readFile: readFile11,
6997
7730
  getFileInfo,
6998
7731
  writeExternalFile,
7732
+ getGitStatus: getGitStatus2,
7733
+ readGitHeadFile: readGitHeadFile2,
6999
7734
  getPlatform
7000
7735
  };
7001
7736
  }
7002
7737
 
7003
- // src/backend/project/git.ts
7004
- import { execFile } from "child_process";
7005
- import { dirname as dirname7, relative as relative8 } from "path";
7006
- import { promisify } from "util";
7007
- var execFileAsync = promisify(execFile);
7008
- function createGitHandlers(ctx) {
7009
- const { storage } = ctx;
7010
- async function getGitStatus({ projectId, cwd }) {
7011
- try {
7012
- const project = storage.getProject(projectId);
7013
- if (!project) throw new Error("Project not found");
7014
- const targetCwd = cwd ? resolveSafePath(project.cwd, cwd) : project.cwd;
7015
- const { stdout } = await execFileAsync("git", ["status", "--porcelain", "-b", "-z"], {
7016
- cwd: targetCwd,
7017
- timeout: 2e3
7018
- });
7019
- const lines = stdout.split("\0").filter(Boolean);
7020
- if (lines.length === 0) return null;
7021
- let branchLine = lines[0];
7022
- let branch = "";
7023
- if (branchLine.startsWith("## ")) {
7024
- branchLine = branchLine.slice(3);
7025
- if (branchLine.startsWith("No commits yet on "))
7026
- branch = branchLine.slice("No commits yet on ".length);
7027
- else if (branchLine.startsWith("HEAD (no branch)")) branch = "HEAD";
7028
- else branch = branchLine.split("...")[0];
7029
- }
7030
- const files = {};
7031
- for (let i = 1; i < lines.length; i++) {
7032
- const line = lines[i];
7033
- const status = line.slice(0, 2);
7034
- if (line.length < 4) continue;
7035
- let path2 = line.slice(3);
7036
- if ((status.includes("R") || status.includes("C")) && i + 1 < lines.length) {
7037
- path2 = lines[i + 1];
7038
- i++;
7039
- }
7040
- files[toPosixPath(path2)] = status;
7041
- }
7042
- return { branch, files };
7043
- } catch {
7044
- return null;
7045
- }
7046
- }
7047
- async function readGitHeadFile({
7048
- projectId,
7049
- relativePath,
7050
- encoding
7051
- }) {
7052
- try {
7053
- const project = storage.getProject(projectId);
7054
- if (!project) throw new Error("Project not found");
7055
- const targetPath = resolveSafePath(project.cwd, relativePath);
7056
- const cwd = dirname7(targetPath);
7057
- const relPath = relative8(cwd, targetPath);
7058
- const { stdout } = await execFileAsync("git", ["show", `HEAD:./${relPath}`], {
7059
- cwd,
7060
- maxBuffer: 10 * 1024 * 1024,
7061
- encoding: encoding ?? "utf8"
7062
- });
7063
- return stdout;
7064
- } catch {
7065
- return "";
7066
- }
7067
- }
7068
- return { getGitStatus, readGitHeadFile };
7069
- }
7070
-
7071
7738
  // src/backend/project/index.ts
7072
7739
  function createProjectModule(ctx, deps) {
7073
7740
  const { sendEvent, onEvent, storage } = ctx;
7074
7741
  const fs2 = createFilesystemState(ctx);
7075
- const git = createGitHandlers(ctx);
7076
7742
  onEvent((channel, payload) => {
7077
7743
  if (channel === "fs-changed") {
7078
7744
  fs2.markProjectFsDirty(payload.projectId);
@@ -7108,8 +7774,7 @@ function createProjectModule(ctx, deps) {
7108
7774
  addProject: addProject2,
7109
7775
  renameProject,
7110
7776
  deleteProject: deleteProject2,
7111
- ...fs2,
7112
- ...git
7777
+ ...fs2
7113
7778
  };
7114
7779
  }
7115
7780
 
@@ -7172,7 +7837,7 @@ async function startSocketServer(socketPath) {
7172
7837
  res.writeHead(404, { "Content-Type": "application/json" });
7173
7838
  res.end(JSON.stringify({ error: "Not found" }));
7174
7839
  });
7175
- return new Promise((resolve8, reject) => {
7840
+ return new Promise((resolve9, reject) => {
7176
7841
  server.listen(socketPath, () => {
7177
7842
  const serverRef = {
7178
7843
  stop: () => {
@@ -7192,7 +7857,7 @@ async function startSocketServer(socketPath) {
7192
7857
  },
7193
7858
  socketPath
7194
7859
  };
7195
- resolve8(serverRef);
7860
+ resolve9(serverRef);
7196
7861
  });
7197
7862
  server.on("error", (err) => {
7198
7863
  console.error("[socket-server] Failed to start:", err);
@@ -8261,7 +8926,7 @@ function createSessionModule(ctx, deps) {
8261
8926
  askUser,
8262
8927
  shareToUser,
8263
8928
  skills,
8264
- search: search2,
8929
+ search,
8265
8930
  memory,
8266
8931
  imageGeneration,
8267
8932
  toolbox,
@@ -8271,7 +8936,7 @@ function createSessionModule(ctx, deps) {
8271
8936
  skills,
8272
8937
  askUser,
8273
8938
  shareToUser,
8274
- search: search2,
8939
+ search,
8275
8940
  memory,
8276
8941
  imageGeneration,
8277
8942
  toolbox
@@ -8289,7 +8954,7 @@ function createSessionModule(ctx, deps) {
8289
8954
  const server = await startSocketServer(options.socketPath);
8290
8955
  toolbox.registerToolboxRoute(server, options.project.cwd);
8291
8956
  skills.registerSkillsRoute(server, options.project.cwd);
8292
- search2.registerSearchRoute(server, options.project.cwd);
8957
+ search.registerSearchRoute(server, options.project.cwd);
8293
8958
  imageGeneration.registerImageGenerationRoute(server, sessionId);
8294
8959
  memory.registerMemoryRoute(server, options.project.id, sessionId);
8295
8960
  askUser.registerAskUserRoute(server, sessionId);
@@ -8455,6 +9120,33 @@ function createSessionModule(ctx, deps) {
8455
9120
  shouldUpdateCache = true;
8456
9121
  } else finalThoughtLevels = session.thoughtLevels;
8457
9122
  }
9123
+ const restorePushback = [];
9124
+ if (finalModels && session.models?.currentModelId && finalModels.currentModelId !== session.models.currentModelId && finalModels.availableModels.some((m) => m.modelId === session.models.currentModelId)) {
9125
+ const cachedModelId = session.models.currentModelId;
9126
+ finalModels = { ...finalModels, currentModelId: cachedModelId };
9127
+ restorePushback.push(
9128
+ b.setSessionModel({ sessionId: session.resumeId, modelId: cachedModelId }).catch((err) => console.warn("[loadSession] Failed to restore model selection:", err))
9129
+ );
9130
+ }
9131
+ if (finalModes && session.modes?.currentModeId && finalModes.currentModeId !== session.modes.currentModeId && finalModes.availableModes.some((m) => m.id === session.modes.currentModeId)) {
9132
+ const cachedModeId = session.modes.currentModeId;
9133
+ finalModes = { ...finalModes, currentModeId: cachedModeId };
9134
+ restorePushback.push(
9135
+ b.setSessionMode({ sessionId: session.resumeId, modeId: cachedModeId }).catch((err) => console.warn("[loadSession] Failed to restore mode selection:", err))
9136
+ );
9137
+ }
9138
+ if (finalThoughtLevels && session.thoughtLevels?.currentThoughtLevelId && finalThoughtLevels.currentThoughtLevelId !== session.thoughtLevels.currentThoughtLevelId && finalThoughtLevels.availableThoughtLevels.some(
9139
+ (m) => m.id === session.thoughtLevels.currentThoughtLevelId
9140
+ )) {
9141
+ const cachedId = session.thoughtLevels.currentThoughtLevelId;
9142
+ finalThoughtLevels = { ...finalThoughtLevels, currentThoughtLevelId: cachedId };
9143
+ restorePushback.push(
9144
+ b.setThoughtLevel({ sessionId: session.resumeId, thoughtLevelId: cachedId }).catch((err) => console.warn("[loadSession] Failed to restore thought level:", err))
9145
+ );
9146
+ }
9147
+ if (restorePushback.length > 0) {
9148
+ await Promise.all(restorePushback);
9149
+ }
8458
9150
  if (shouldUpdateCache || b.initializeInfo) {
8459
9151
  storage.updateSession(
8460
9152
  session.id,
@@ -8521,7 +9213,7 @@ function createSessionModule(ctx, deps) {
8521
9213
  `[SendPrompt] Killed ${killed} agent terminal(s) from previous generation for session ${sessionId}`
8522
9214
  );
8523
9215
  }
8524
- await new Promise((resolve8) => setTimeout(resolve8, 30));
9216
+ await new Promise((resolve9) => setTimeout(resolve9, 30));
8525
9217
  }
8526
9218
  if (!session.title) {
8527
9219
  const firstTextContent = contents.find((c) => c.type === "text");
@@ -8541,15 +9233,20 @@ function createSessionModule(ctx, deps) {
8541
9233
  ctx,
8542
9234
  mcpDeps
8543
9235
  );
8544
- await b.loadSession({
8545
- sessionId: session.resumeId,
8546
- cwd: session.cwd,
8547
- mcpServers: activeMcpServers
8548
- });
8549
- await createSessionSocketServer(session.id, {
8550
- socketPath,
8551
- project
8552
- });
9236
+ notif.addRestoring(session.id);
9237
+ try {
9238
+ await b.loadSession({
9239
+ sessionId: session.resumeId,
9240
+ cwd: session.cwd,
9241
+ mcpServers: activeMcpServers
9242
+ });
9243
+ await createSessionSocketServer(session.id, {
9244
+ socketPath,
9245
+ project
9246
+ });
9247
+ } finally {
9248
+ notif.removeRestoring(session.id);
9249
+ }
8553
9250
  }
8554
9251
  storage.updateSession(sessionId, { isStreaming: true });
8555
9252
  const updated = storage.getSession(sessionId);
@@ -9389,22 +10086,54 @@ function createInferenceModule(_ctx, deps) {
9389
10086
  const textChunks = [];
9390
10087
  const terminalLogs = {};
9391
10088
  const agentInfo = resolveAgentInfo(agentId);
10089
+ let currentSessionId = null;
10090
+ function processNotification(notification) {
10091
+ let results = [notification];
10092
+ if (currentSessionId) {
10093
+ for (const adapter of adapters) {
10094
+ const next = [];
10095
+ for (const n of results) {
10096
+ const processed = adapter.preprocessNotification(n, currentSessionId, agentId);
10097
+ if (processed !== null) {
10098
+ next.push(...processed);
10099
+ }
10100
+ }
10101
+ results = next;
10102
+ }
10103
+ }
10104
+ if (results.length === 0) return;
10105
+ for (const result of results) {
10106
+ notifications.push(result);
10107
+ if (result.update?.sessionUpdate === "agent_message_chunk") {
10108
+ const content = result.update.content;
10109
+ if (content?.type === "text" && content.text) {
10110
+ textChunks.push(content.text);
10111
+ }
10112
+ }
10113
+ }
10114
+ }
9392
10115
  const bridge = new ACPBridge(agentId, {
9393
10116
  agentInfo,
9394
10117
  cwd,
9395
- onSessionConnect: () => {
10118
+ extNotificationSpecs,
10119
+ agentEnv,
10120
+ onSessionConnect: (connection) => {
10121
+ currentSessionId = `${agentId}:${connection.sessionId}`;
9396
10122
  },
9397
10123
  onSessionUpdate: (notification) => {
9398
- notifications.push(notification);
9399
- if (notification.update?.sessionUpdate === "agent_message_chunk") {
9400
- const content = notification.update.content;
9401
- if (content?.type === "text" && content.text) {
9402
- textChunks.push(content.text);
10124
+ processNotification(notification);
10125
+ },
10126
+ onExtNotification: (method, params) => {
10127
+ for (const adapter of adapters) {
10128
+ const results = adapter.handleExtNotification(method, params, currentSessionId, agentId);
10129
+ if (results.length > 0) {
10130
+ for (const result of results) {
10131
+ processNotification(result);
10132
+ }
10133
+ return;
9403
10134
  }
9404
10135
  }
9405
10136
  },
9406
- onExtNotification: () => {
9407
- },
9408
10137
  onPermissionRequest: async (request) => {
9409
10138
  const opt = request.options.find((o) => o.kind === "allow_always") ?? request.options.find((o) => o.kind === "allow_once") ?? request.options[0];
9410
10139
  return { outcome: { outcome: "selected", optionId: opt?.optionId ?? "allow" } };
@@ -10143,7 +10872,15 @@ function createMemoryModule(_ctx, deps) {
10143
10872
  if (file.entries.length === 0 && !existsSync8(getMemoryPath(projectId))) {
10144
10873
  return null;
10145
10874
  }
10146
- return file;
10875
+ return { version: file.version, entries: getMemoEntries(file.entries) };
10876
+ }
10877
+ function deleteMemoryEntry(projectId, entryId) {
10878
+ const file = readMemoryFile(projectId);
10879
+ const index = file.entries.findIndex((entry) => getMemoryEntryId(entry.text) === entryId);
10880
+ if (index === -1) return false;
10881
+ file.entries.splice(index, 1);
10882
+ writeMemoryFile(projectId, file);
10883
+ return true;
10147
10884
  }
10148
10885
  function clearMemory(projectId) {
10149
10886
  const memoryPath = getMemoryPath(projectId);
@@ -10159,6 +10896,7 @@ function createMemoryModule(_ctx, deps) {
10159
10896
  registerMemoryRoute,
10160
10897
  buildMemoryMcpServer,
10161
10898
  getMemory,
10899
+ deleteMemoryEntry,
10162
10900
  clearMemory,
10163
10901
  getFilePath
10164
10902
  };
@@ -10348,7 +11086,7 @@ function createImageGenerationModule(ctx, deps) {
10348
11086
  }
10349
11087
 
10350
11088
  // src/backend/toolbox.ts
10351
- import { join as join23, resolve as resolve7, dirname as dirname9, basename as basename4, extname as extname3 } from "path";
11089
+ import { join as join23, resolve as resolve8, dirname as dirname9, basename as basename4, extname as extname3 } from "path";
10352
11090
  import { writeFile as writeFile6 } from "fs/promises";
10353
11091
  import { createHash as createHash6, randomUUID as randomUUID13, randomInt } from "crypto";
10354
11092
  import * as qr from "qr-image";
@@ -10595,15 +11333,15 @@ function createToolboxModule(_ctx) {
10595
11333
  });
10596
11334
  server.registry("toolbox/image-metadata", async (payload) => {
10597
11335
  const { path: imgPath } = imageMetadataRequestSchema.parse(payload);
10598
- const absPath = resolve7(projectDir, imgPath);
11336
+ const absPath = resolve8(projectDir, imgPath);
10599
11337
  const sharp = await getSharp();
10600
11338
  const metadata = await sharp(absPath).metadata();
10601
11339
  return { result: extractMetadata(metadata) };
10602
11340
  });
10603
11341
  server.registry("toolbox/image-thumbnail", async (payload) => {
10604
11342
  const { path: imgPath, width, output } = imageThumbnailRequestSchema.parse(payload);
10605
- const absPath = resolve7(projectDir, imgPath);
10606
- const outputPath = output ? resolve7(projectDir, output) : join23(
11343
+ const absPath = resolve8(projectDir, imgPath);
11344
+ const outputPath = output ? resolve8(projectDir, output) : join23(
10607
11345
  dirname9(absPath),
10608
11346
  `${basename4(absPath, extname3(absPath))}.thumb${width}${extname3(absPath)}`
10609
11347
  );
@@ -10614,7 +11352,7 @@ function createToolboxModule(_ctx) {
10614
11352
  });
10615
11353
  server.registry("toolbox/image-resize", async (payload) => {
10616
11354
  const { path: imgPath, width, height, fit, output } = imageResizeRequestSchema.parse(payload);
10617
- const absPath = resolve7(projectDir, imgPath);
11355
+ const absPath = resolve8(projectDir, imgPath);
10618
11356
  const sharp = await getSharp();
10619
11357
  const resized = await sharp(absPath).resize({ width, height, fit }).toBuffer();
10620
11358
  const resizedMeta = await sharp(resized).metadata();
@@ -10622,15 +11360,15 @@ function createToolboxModule(_ctx) {
10622
11360
  const actualHeight = resizedMeta.height ?? height ?? 0;
10623
11361
  const ext = extname3(absPath);
10624
11362
  const base = basename4(absPath, ext);
10625
- const outputPath = output ? resolve7(projectDir, output) : join23(dirname9(absPath), `${base}.${actualWidth}x${actualHeight}${ext}`);
11363
+ const outputPath = output ? resolve8(projectDir, output) : join23(dirname9(absPath), `${base}.${actualWidth}x${actualHeight}${ext}`);
10626
11364
  await writeFile6(outputPath, resized);
10627
11365
  const metadata = await sharp(outputPath).metadata();
10628
11366
  return { result: { output: outputPath, metadata: extractMetadata(metadata) } };
10629
11367
  });
10630
11368
  server.registry("toolbox/image-convert", async (payload) => {
10631
11369
  const { path: imgPath, format, quality, output } = imageConvertRequestSchema.parse(payload);
10632
- const absPath = resolve7(projectDir, imgPath);
10633
- const outputPath = output ? resolve7(projectDir, output) : join23(dirname9(absPath), `${basename4(absPath, extname3(absPath))}.${format}`);
11370
+ const absPath = resolve8(projectDir, imgPath);
11371
+ const outputPath = output ? resolve8(projectDir, output) : join23(dirname9(absPath), `${basename4(absPath, extname3(absPath))}.${format}`);
10634
11372
  const sharp = await getSharp();
10635
11373
  let pipeline = sharp(absPath);
10636
11374
  const opts = {};
@@ -10642,7 +11380,7 @@ function createToolboxModule(_ctx) {
10642
11380
  });
10643
11381
  server.registry("toolbox/image-qrcode", async (payload) => {
10644
11382
  const { text, output, size, margin, errorCorrection } = qrCodeRequestSchema.parse(payload);
10645
- const outputPath = resolve7(projectDir, output ?? "qrcode.png");
11383
+ const outputPath = resolve8(projectDir, output ?? "qrcode.png");
10646
11384
  const png = qr.imageSync(text, {
10647
11385
  type: "png",
10648
11386
  size,
@@ -10691,11 +11429,11 @@ function initBackend(emitter) {
10691
11429
  const askUser = createAskUserModule(ctx, { ilink: ilink.state });
10692
11430
  const shareToUser = createShareToUserModule(ctx, { ilink: ilink.state });
10693
11431
  const skills = createSkillsModule(ctx);
10694
- const search2 = createSearchModule(ctx);
11432
+ const search = createSearchModule(ctx);
10695
11433
  const watcher2 = createWatcherModule(ctx);
10696
11434
  const toolbox = createToolboxModule(ctx);
10697
11435
  const bridgeConnect = createBridgeConnectModule(ctx, { askUser });
10698
- const _inference = createInferenceModule(ctx, { skills, search: search2, toolbox });
11436
+ const _inference = createInferenceModule(ctx, { skills, search, toolbox });
10699
11437
  const memory = createMemoryModule(ctx, { inference: _inference });
10700
11438
  const imageGeneration = createImageGenerationModule(ctx, { ilink: ilink.state });
10701
11439
  const session = createSessionModule(ctx, {
@@ -10703,7 +11441,7 @@ function initBackend(emitter) {
10703
11441
  askUser,
10704
11442
  shareToUser,
10705
11443
  skills,
10706
- search: search2,
11444
+ search,
10707
11445
  memory,
10708
11446
  imageGeneration,
10709
11447
  toolbox,
@@ -11071,6 +11809,9 @@ function initBackend(emitter) {
11071
11809
  async getMemory({ projectId }) {
11072
11810
  return memory.getMemory(projectId);
11073
11811
  },
11812
+ async deleteMemoryEntry({ projectId, entryId }) {
11813
+ return memory.deleteMemoryEntry(projectId, entryId);
11814
+ },
11074
11815
  async clearMemory({ projectId }) {
11075
11816
  memory.clearMemory(projectId);
11076
11817
  },
@@ -11085,7 +11826,7 @@ function initBackend(emitter) {
11085
11826
  await ilink.stopIlink({ logout: false });
11086
11827
  session.clearSession();
11087
11828
  await bridgeConnect.clearAll();
11088
- await new Promise((resolve8) => setTimeout(resolve8, 100));
11829
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
11089
11830
  terminal.killAllTerminals();
11090
11831
  await watcher2.stopAll();
11091
11832
  for (const file of await readdir2(TEMP_DIR)) {
@@ -11096,7 +11837,7 @@ function initBackend(emitter) {
11096
11837
  }
11097
11838
 
11098
11839
  // package.json
11099
- var version = "0.1.46";
11840
+ var version = "0.1.49";
11100
11841
 
11101
11842
  // src/server/main.ts
11102
11843
  var port;
@@ -11125,6 +11866,14 @@ Options:
11125
11866
  process.exit(0);
11126
11867
  }
11127
11868
  }
11869
+ var proxySettings = storageOps.getSettings().proxy;
11870
+ if (proxySettings.mode === "system") {
11871
+ const detected = detectSystemProxy();
11872
+ applyProxy(detected);
11873
+ console.log(`[proxy] system proxy: ${detected.httpProxy || detected.httpsProxy || "none"}`);
11874
+ } else {
11875
+ applyProxy(settingProxyInfoToProxyConfig(proxySettings));
11876
+ }
11128
11877
  var { backendHandlers, closeBackend } = initBackend(() => false);
11129
11878
  backendHandlers.startWebUIServer({ port, token }).then(({ url }) => {
11130
11879
  const title = `Fello Server v${version}`;