autohand-cli 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (551) hide show
  1. package/README.md +173 -74
  2. package/dist/AgentRegistry-EGBDIUAK.cjs +10 -0
  3. package/dist/{AgentRegistry-7LDL5HJH.js → AgentRegistry-XPWSVO3Q.js} +3 -3
  4. package/dist/{AutomodeManager-MWLKGPZK.js → AutomodeManager-APLLPEYJ.js} +32 -18
  5. package/dist/{AutomodeManager-NYIZNODK.cjs → AutomodeManager-MPSXT2RH.cjs} +38 -24
  6. package/dist/CommunitySkillsCache-2OIUV227.cjs +8 -0
  7. package/dist/CommunitySkillsCache-ZEQWP6YM.js +8 -0
  8. package/dist/GitHubRegistryFetcher-CYJLF2XL.cjs +7 -0
  9. package/dist/{GitHubRegistryFetcher-6JQ5JEDZ.js → GitHubRegistryFetcher-J2BWPXJF.js} +2 -2
  10. package/dist/HookManager-CWLTFKWO.js +7 -0
  11. package/dist/HookManager-TMAJQU4S.cjs +7 -0
  12. package/dist/{ImportWizard-35YBJ4AM.cjs → ImportWizard-MQXEED2U.cjs} +41 -17
  13. package/dist/{ImportWizard-XH7CINCH.js → ImportWizard-QBKQEXDW.js} +35 -11
  14. package/dist/LearnAdvisor-46FG2XIP.js +9 -0
  15. package/dist/LearnAdvisor-XBRDNAGH.cjs +9 -0
  16. package/dist/McpClientManager-BNSKLHIN.cjs +8 -0
  17. package/dist/{McpClientManager-7RM6YT35.js → McpClientManager-SL35BR24.js} +2 -2
  18. package/dist/MemoryManager-34L4YOKA.cjs +8 -0
  19. package/dist/MemoryManager-WJMLPWGU.js +8 -0
  20. package/dist/NVIDIAProvider-2HR737UE.js +14 -0
  21. package/dist/NVIDIAProvider-MVTL62PR.cjs +14 -0
  22. package/dist/PermissionManager-5OOJ7FAT.cjs +11 -0
  23. package/dist/{PermissionManager-ATUV34LQ.js → PermissionManager-KMYILJ4Z.js} +4 -4
  24. package/dist/{ProjectProfiler-ZDWR2ODG.cjs → ProjectProfiler-CDAE7ECW.cjs} +2 -1
  25. package/dist/{ProjectProfiler-UMJJSOCE.js → ProjectProfiler-NZTJDRHD.js} +2 -1
  26. package/dist/ProviderFactory-C3YPXTDD.cjs +11 -0
  27. package/dist/ProviderFactory-HFPRVQ25.js +11 -0
  28. package/dist/SessionManager-PNBTJJTQ.js +10 -0
  29. package/dist/SessionManager-WAPTFMDO.cjs +10 -0
  30. package/dist/SkillsRegistry-4RRD5GMX.js +9 -0
  31. package/dist/SkillsRegistry-7AJP74GJ.cjs +9 -0
  32. package/dist/SubAgent-FDIH3DXB.js +11 -0
  33. package/dist/SubAgent-HVL2ICVZ.cjs +11 -0
  34. package/dist/{SyncApiClient-LVIO4C2S.js → SyncApiClient-LRPFNCKJ.js} +2 -2
  35. package/dist/SyncApiClient-VMBOLQ6H.cjs +11 -0
  36. package/dist/about-BW3PDZUU.js +14 -0
  37. package/dist/about-FCAX37YC.cjs +14 -0
  38. package/dist/acp-EOETGAHC.cjs +1517 -0
  39. package/dist/acp-VHEL7BOW.js +1517 -0
  40. package/dist/actionExecutor-33I47NZS.js +24 -0
  41. package/dist/actionExecutor-4YBMR3YH.cjs +24 -0
  42. package/dist/add-dir-7SS6KSH5.cjs +11 -0
  43. package/dist/add-dir-VFX7QT4E.js +11 -0
  44. package/dist/agent-DMRUFU4M.cjs +116 -0
  45. package/dist/agent-WCJEYQJT.js +116 -0
  46. package/dist/agents/builtin/code-cleaner.md +1 -1
  47. package/dist/agents/builtin/docs-writer.md +1 -1
  48. package/dist/agents/builtin/researcher.md +2 -2
  49. package/dist/agents/builtin/reviewer.md +1 -1
  50. package/dist/agents/builtin/tester.md +1 -1
  51. package/dist/agents/builtin/todo-resolver.md +1 -1
  52. package/dist/agents-CHROO3VU.cjs +17 -0
  53. package/dist/agents-UVDUL65K.js +17 -0
  54. package/dist/agents-new-AUBWSOXP.js +17 -0
  55. package/dist/agents-new-Y562WC47.cjs +17 -0
  56. package/dist/{autoSkill-6TGBTEQD.js → autoSkill-EFMK6WU6.js} +3 -3
  57. package/dist/autoSkill-YOLLFTP2.cjs +20 -0
  58. package/dist/automode-BMYSRM34.js +10 -0
  59. package/dist/automode-DBLKTTKD.cjs +10 -0
  60. package/dist/browserToolBridge-BXRQB4B4.cjs +58 -0
  61. package/dist/browserToolBridge-F5N66PE7.js +58 -0
  62. package/dist/{cc-7LEIJ3KF.js → cc-AYEP2CA3.js} +1 -1
  63. package/dist/{cc-Q5MM4AWC.cjs → cc-S2QLQFBR.cjs} +1 -1
  64. package/dist/chrome-ATC4OO5I.cjs +20 -0
  65. package/dist/chrome-NHJ44WUN.js +50 -0
  66. package/dist/chrome-O62WXV7F.js +20 -0
  67. package/dist/chrome-XHJLCO4M.cjs +50 -0
  68. package/dist/chromeSkill-53TH55PM.js +105 -0
  69. package/dist/chromeSkill-THW7N4IY.cjs +105 -0
  70. package/dist/{chunk-HOAHWIQ5.cjs → chunk-2CGE7ZV3.cjs} +26 -26
  71. package/dist/chunk-2H5O745H.js +63 -0
  72. package/dist/chunk-2HOLOHVK.js +2219 -0
  73. package/dist/{chunk-3PDTTAKJ.js → chunk-2QL6MNXG.js} +15 -8
  74. package/dist/{chunk-PGRH5Q77.cjs → chunk-2VHB43IX.cjs} +35 -6
  75. package/dist/{chunk-VG34MG2U.js → chunk-37M5UM6I.js} +9 -6
  76. package/dist/{chunk-6HYLHBQG.cjs → chunk-3DDL2E55.cjs} +20 -16
  77. package/dist/chunk-3EDDDZS2.cjs +5 -0
  78. package/dist/{chunk-6OYHF6MF.js → chunk-3GUEUCZK.js} +28 -4
  79. package/dist/{chunk-N254NRHT.cjs → chunk-3HT76LNN.cjs} +9 -2
  80. package/dist/{chunk-DVUHHH3B.cjs → chunk-3KLSNNRW.cjs} +4 -4
  81. package/dist/chunk-3LJJG5YY.cjs +387 -0
  82. package/dist/chunk-3OF56EMA.cjs +197 -0
  83. package/dist/chunk-3PXKRVCW.js +108 -0
  84. package/dist/{chunk-IKGWDOGU.cjs → chunk-3S563FNF.cjs} +160 -79
  85. package/dist/chunk-3UT7R3XV.js +663 -0
  86. package/dist/chunk-4256YRCO.cjs +80 -0
  87. package/dist/chunk-46C73ZKK.cjs +663 -0
  88. package/dist/chunk-46MTALKD.js +44 -0
  89. package/dist/{chunk-AEJH23FO.cjs → chunk-47PHDKNW.cjs} +6 -6
  90. package/dist/chunk-4LMUDS2K.js +124 -0
  91. package/dist/{chunk-HLHTG5ZU.cjs → chunk-5CMYEM3R.cjs} +14 -12
  92. package/dist/{chunk-MBBY4ZIK.js → chunk-5F6ZKSHO.js} +4 -1
  93. package/dist/chunk-5JFTY3VU.js +74 -0
  94. package/dist/chunk-5JTTM5SC.js +59 -0
  95. package/dist/{chunk-IETRBBMP.cjs → chunk-5K3CDSWZ.cjs} +108 -31
  96. package/dist/{chunk-GJH7XMSK.js → chunk-5VHP6HDQ.js} +8 -6
  97. package/dist/{chunk-6ZCULLCA.js → chunk-62RTC3XX.js} +1 -1
  98. package/dist/{chunk-MSED7RH2.cjs → chunk-6GUODJKM.cjs} +112 -41
  99. package/dist/{chunk-47CKWKEX.cjs → chunk-6HH236FV.cjs} +9 -4
  100. package/dist/{chunk-WHE2SWHU.js → chunk-6NVAK6CK.js} +2 -2
  101. package/dist/chunk-6R25D2H5.js +121 -0
  102. package/dist/{chunk-3PCTTUNW.cjs → chunk-6XVVIY54.cjs} +55 -25
  103. package/dist/{chunk-3L53OA4E.cjs → chunk-75EDROHL.cjs} +10 -10
  104. package/dist/{chunk-G4CAKI3V.js → chunk-7HPWMALN.js} +7 -2
  105. package/dist/chunk-7JLT2VNW.cjs +18963 -0
  106. package/dist/chunk-7LWQCE4Y.cjs +987 -0
  107. package/dist/{chunk-OLSBBZW6.cjs → chunk-7MU7LWF3.cjs} +5 -5
  108. package/dist/{chunk-HLQV64Y5.js → chunk-7RFJB75Y.js} +140 -59
  109. package/dist/{chunk-X2MSVKDV.js → chunk-A7HHCIDQ.js} +2 -2
  110. package/dist/{chunk-SKYG33B2.cjs → chunk-AC7DZ6SK.cjs} +3 -3
  111. package/dist/{chunk-XX2ZO7DS.js → chunk-ACDQGA4Z.js} +90 -16
  112. package/dist/{chunk-CZXGCVTR.cjs → chunk-AOKCI722.cjs} +2 -2
  113. package/dist/chunk-ARBEHFCG.js +715 -0
  114. package/dist/{chunk-OOKY3HPZ.js → chunk-AT7OWLY5.js} +50 -9
  115. package/dist/chunk-AU6JAGZJ.cjs +231 -0
  116. package/dist/chunk-AUFNACED.js +18963 -0
  117. package/dist/{chunk-CDBPBM2K.cjs → chunk-AUYSIEVV.cjs} +3 -3
  118. package/dist/chunk-B4HSNOIH.cjs +354 -0
  119. package/dist/{chunk-EGMZDTSL.js → chunk-B5CGDNMR.js} +10 -2
  120. package/dist/{chunk-34M3HWLR.js → chunk-BFQDQRDE.js} +2 -2
  121. package/dist/{chunk-2AA5MFES.js → chunk-BL2UC7HC.js} +8 -5
  122. package/dist/{chunk-LNMYK2F5.cjs → chunk-BQ22N3TX.cjs} +56 -41
  123. package/dist/chunk-BQU3HAE7.js +21 -0
  124. package/dist/chunk-BWF4VDYE.js +3897 -0
  125. package/dist/chunk-BYE7RQFZ.cjs +121 -0
  126. package/dist/{chunk-APIXPPMT.js → chunk-CBFH2J3O.js} +855 -33
  127. package/dist/chunk-CCVMREXI.js +420 -0
  128. package/dist/chunk-CFAWTLSC.js +13 -0
  129. package/dist/{chunk-G27PQQFD.js → chunk-CFFE4VA3.js} +1 -1
  130. package/dist/{chunk-ZYQMLKOK.cjs → chunk-CH2J4PVE.cjs} +212 -70
  131. package/dist/{chunk-7BTSG4ME.cjs → chunk-CHI52KFR.cjs} +855 -33
  132. package/dist/{chunk-DJDE4DTT.cjs → chunk-CWINVFRI.cjs} +25 -19
  133. package/dist/{chunk-HXGBSJL5.cjs → chunk-D2OSPLYC.cjs} +2 -2
  134. package/dist/{chunk-GBHDROGL.js → chunk-D6GZBSOX.js} +16 -4
  135. package/dist/{chunk-CNBKZEX5.cjs → chunk-DA7NBAJK.cjs} +49 -17
  136. package/dist/chunk-DEQVRSV5.cjs +866 -0
  137. package/dist/{chunk-RGR6ME5J.cjs → chunk-DI57A4BX.cjs} +25 -28
  138. package/dist/{chunk-WM5PAOTQ.cjs → chunk-DIZTWFVR.cjs} +1649 -484
  139. package/dist/{chunk-YZXUDM5X.js → chunk-DLP436GI.js} +204 -62
  140. package/dist/{chunk-OHUZKDGX.js → chunk-DMRXF5DU.js} +3 -3
  141. package/dist/{chunk-U46VYPLR.cjs → chunk-DPSIGY6L.cjs} +9 -9
  142. package/dist/{chunk-DN573ME7.cjs → chunk-DRWDEHE5.cjs} +4 -4
  143. package/dist/{chunk-SEKD5FH3.cjs → chunk-E26KKI46.cjs} +5 -2
  144. package/dist/{chunk-J4Q7XR3G.js → chunk-E46DJH5S.js} +3 -3
  145. package/dist/{chunk-Q7XSCYND.cjs → chunk-E6GFD7VR.cjs} +49 -26
  146. package/dist/chunk-ES2HJQ4N.js +37 -0
  147. package/dist/chunk-EZJHLOWP.js +80 -0
  148. package/dist/chunk-FFBDRUO5.cjs +59 -0
  149. package/dist/{chunk-AYSFIUFW.js → chunk-FGT6KK6T.js} +38 -15
  150. package/dist/{chunk-SAHBLB3E.js → chunk-FP46B4X3.js} +208 -3
  151. package/dist/{chunk-DSPQEHDT.js → chunk-FQAVGSPW.js} +2 -2
  152. package/dist/chunk-FQVG6ZHF.js +197 -0
  153. package/dist/chunk-GBMDFWJX.cjs +152 -0
  154. package/dist/{chunk-DRE2RXBZ.js → chunk-GGLKUENP.js} +1605 -440
  155. package/dist/{chunk-S52YW5ZQ.js → chunk-GNBBIAMD.js} +16 -19
  156. package/dist/{chunk-MYISNQH4.js → chunk-GWO66KBI.js} +1 -1
  157. package/dist/chunk-GWY26SUD.cjs +63 -0
  158. package/dist/{chunk-YGN4CQIP.js → chunk-GZ6DV2UG.js} +1 -1
  159. package/dist/{chunk-EZMINVLU.js → chunk-H4D2Q2AL.js} +5 -2
  160. package/dist/chunk-HDK2EHVH.cjs +570 -0
  161. package/dist/chunk-HJIXWGQZ.js +139 -0
  162. package/dist/{chunk-6RF7UKUS.js → chunk-HKYZSUQ5.js} +48 -47
  163. package/dist/{chunk-LQGVEP3E.js → chunk-HQUSEWT4.js} +45 -13
  164. package/dist/{chunk-HTLINWX6.cjs → chunk-HQWQZML5.cjs} +16 -13
  165. package/dist/{chunk-DVZOENQ7.cjs → chunk-HS4USDND.cjs} +9 -4
  166. package/dist/chunk-HSCUPEA4.cjs +3897 -0
  167. package/dist/{chunk-JCLYQ2JC.js → chunk-HXJEGMGB.js} +12 -6
  168. package/dist/{chunk-LJFUXC56.cjs → chunk-HXQREVTA.cjs} +9 -6
  169. package/dist/{chunk-SCXX4LW5.js → chunk-I24CWKKK.js} +15 -8
  170. package/dist/chunk-IAGCRVJ3.js +355 -0
  171. package/dist/chunk-IEXKKKOF.cjs +92 -0
  172. package/dist/{chunk-5IXII4HX.cjs → chunk-IGMPWJ2I.cjs} +19 -12
  173. package/dist/chunk-IKUMVBCW.cjs +33 -0
  174. package/dist/{chunk-XTB6VJVQ.cjs → chunk-J2K57QM7.cjs} +6 -6
  175. package/dist/{chunk-O4IF4NJT.cjs → chunk-J5ADZN6V.cjs} +57 -56
  176. package/dist/chunk-J5HE6CUM.cjs +124 -0
  177. package/dist/{chunk-JS7IPR7P.js → chunk-JAQO6XDB.js} +31 -2
  178. package/dist/chunk-JIMSII7R.js +987 -0
  179. package/dist/chunk-JJ4KA7HK.cjs +2219 -0
  180. package/dist/chunk-JMN3GZU6.js +570 -0
  181. package/dist/{chunk-X5VSP65C.cjs → chunk-JP3YHTQ2.cjs} +4 -4
  182. package/dist/{chunk-SKV2F3NM.js → chunk-JYKPWK5O.js} +1 -1
  183. package/dist/{chunk-NNPAM4HC.cjs → chunk-KNTUI4TZ.cjs} +12 -6
  184. package/dist/{chunk-HIVRCQS2.js → chunk-L4F7SUYL.js} +56 -25
  185. package/dist/{chunk-C5IJIM2V.cjs → chunk-LDJQ5QHG.cjs} +68 -37
  186. package/dist/{chunk-ULQ6MDSJ.cjs → chunk-LFDPTJYF.cjs} +43 -35
  187. package/dist/chunk-LJD7KR3L.cjs +44 -0
  188. package/dist/chunk-LN7D3EJZ.js +387 -0
  189. package/dist/{chunk-643VRA5S.cjs → chunk-LQBONA55.cjs} +32 -8
  190. package/dist/{chunk-NCC6ETZS.js → chunk-LUMV3DB2.js} +41 -33
  191. package/dist/chunk-M4KNC5BQ.js +78 -0
  192. package/dist/chunk-MO4KP6XS.cjs +229 -0
  193. package/dist/{chunk-BVKXEQVG.cjs → chunk-MOJ7ADW4.cjs} +22 -10
  194. package/dist/chunk-MPULXVC4.cjs +715 -0
  195. package/dist/{chunk-X5YJ34FZ.cjs → chunk-MQESBFBZ.cjs} +46 -23
  196. package/dist/chunk-MUNUUFU7.cjs +21 -0
  197. package/dist/{chunk-X3WS5LDG.js → chunk-MX75JYIY.js} +7 -5
  198. package/dist/chunk-MXVIDIC6.cjs +139 -0
  199. package/dist/{chunk-3K2ESU53.cjs → chunk-N6O3XUZ2.cjs} +2 -2
  200. package/dist/{chunk-IVM5F2AE.js → chunk-NBGOIFKP.js} +265 -18
  201. package/dist/{chunk-SLQAYV3W.js → chunk-NMQ47RCG.js} +8 -2
  202. package/dist/{chunk-JYTDYJVW.js → chunk-O64I2GYI.js} +1 -1
  203. package/dist/{chunk-IFFXSTOM.cjs → chunk-O6TQP7U7.cjs} +3 -3
  204. package/dist/{chunk-AYS2ASM7.js → chunk-OHWMWKJQ.js} +1 -1
  205. package/dist/{chunk-N23UAW4I.js → chunk-OM24WXEE.js} +7 -2
  206. package/dist/{chunk-MAKMSQMQ.cjs → chunk-OPNI6O7F.cjs} +8 -6
  207. package/dist/chunk-OR67YXQK.cjs +13 -0
  208. package/dist/{chunk-QOXPOR5D.js → chunk-OV3PVUYN.js} +115 -44
  209. package/dist/{chunk-TNZRZQ7Q.js → chunk-PB7W7R72.js} +3 -78
  210. package/dist/chunk-PCM3N3CL.cjs +37 -0
  211. package/dist/{chunk-A4IJHHV7.cjs → chunk-PDHT7LQS.cjs} +52 -11
  212. package/dist/{chunk-LA7H35XM.cjs → chunk-PHJO5YAL.cjs} +9 -9
  213. package/dist/{chunk-KPELYZ6L.js → chunk-PQLKJCIE.js} +2 -2
  214. package/dist/chunk-PUD76XQT.cjs +78 -0
  215. package/dist/chunk-Q2IL4DDI.cjs +355 -0
  216. package/dist/{chunk-WPVWQSL7.cjs → chunk-Q6AC3PHY.cjs} +16 -13
  217. package/dist/{chunk-XRZEUWKF.js → chunk-QCHIDZBA.js} +1 -1
  218. package/dist/{chunk-IQ5RXU6O.js → chunk-QEGOB6QV.js} +1 -1
  219. package/dist/{chunk-JSBRDJBE.js → chunk-QGM4M3NI.js} +8 -1
  220. package/dist/chunk-QKP772OZ.js +4291 -0
  221. package/dist/chunk-QQ7PANOP.js +59 -0
  222. package/dist/{chunk-YHD6TUIR.cjs → chunk-QW2RW2GY.cjs} +2 -0
  223. package/dist/chunk-RAKO7UN7.js +114 -0
  224. package/dist/chunk-RBHANOYY.js +33 -0
  225. package/dist/chunk-RBZ7AFX7.cjs +29 -0
  226. package/dist/{chunk-TXSDBGKX.cjs → chunk-REMGR23V.cjs} +46 -49
  227. package/dist/chunk-ROLA6EFO.cjs +85 -0
  228. package/dist/{chunk-TBEGGJNC.cjs → chunk-SOLBYSLY.cjs} +33 -16
  229. package/dist/{chunk-FKSDEWDH.js → chunk-SWCQM52V.js} +68 -25
  230. package/dist/{chunk-H5SWOLG6.js → chunk-TBOLJDUG.js} +39 -24
  231. package/dist/chunk-TH26BQJG.js +101 -0
  232. package/dist/{chunk-245KJE5Y.cjs → chunk-TJNBASFD.cjs} +14 -6
  233. package/dist/chunk-TKKN34TV.js +229 -0
  234. package/dist/chunk-TQ33WBY5.cjs +74 -0
  235. package/dist/{chunk-EGFT4PGW.js → chunk-TWQDAUZU.js} +5 -2
  236. package/dist/{chunk-OGV4WJ5L.cjs → chunk-TXPSTCG7.cjs} +74 -59
  237. package/dist/{chunk-CAMZTXV6.js → chunk-U4C3HW6P.js} +67 -52
  238. package/dist/{chunk-5P2NXKP3.js → chunk-UEIXJG45.js} +104 -76
  239. package/dist/{chunk-22D2CNTP.cjs → chunk-UGFVM77J.cjs} +5 -2
  240. package/dist/chunk-UOQECODR.js +34 -0
  241. package/dist/chunk-UR27UDTB.js +354 -0
  242. package/dist/chunk-UWFG2R2I.cjs +420 -0
  243. package/dist/{chunk-Y72HH2TF.cjs → chunk-UXLW45ZE.cjs} +102 -28
  244. package/dist/{chunk-FPHU2ES6.cjs → chunk-VBOFPU5M.cjs} +6 -0
  245. package/dist/{chunk-JX3DFKBI.js → chunk-VDWJMWDF.js} +54 -24
  246. package/dist/{chunk-LENHP55G.cjs → chunk-VGEV44V2.cjs} +1076 -158
  247. package/dist/{chunk-33RSHBDH.js → chunk-VKBIE6I6.js} +38 -7
  248. package/dist/{chunk-CWMZKFTT.js → chunk-VRMZO6TB.js} +31 -8
  249. package/dist/chunk-VUGOOGHB.js +400 -0
  250. package/dist/chunk-WBU4Q4GS.cjs +400 -0
  251. package/dist/chunk-WGLBC5AY.cjs +59 -0
  252. package/dist/{chunk-KWXVKLQ5.cjs → chunk-WGNMOVMT.cjs} +7 -82
  253. package/dist/{chunk-RKJTGGMU.cjs → chunk-WKRDBCP2.cjs} +221 -16
  254. package/dist/chunk-WRTXCQ3V.cjs +4291 -0
  255. package/dist/chunk-WTB7AFL6.cjs +101 -0
  256. package/dist/{chunk-NDMIPTV4.js → chunk-WZV6UVPY.js} +8 -3
  257. package/dist/chunk-XF2WIKHR.cjs +34 -0
  258. package/dist/{chunk-L3WAH3EM.cjs → chunk-XGMI6IYB.cjs} +46 -15
  259. package/dist/{chunk-FW774QXH.js → chunk-XIVFAD2L.js} +1048 -130
  260. package/dist/chunk-XV2HXRHX.js +85 -0
  261. package/dist/{chunk-72FKPBT5.js → chunk-Y3M2DABP.js} +16 -12
  262. package/dist/{chunk-QNGEW5TC.js → chunk-YV63VW4K.js} +1 -1
  263. package/dist/{chunk-UJ2JSM6H.js → chunk-YVQI26H4.js} +2 -0
  264. package/dist/{chunk-RD5XAJR2.cjs → chunk-YWTIXHU6.cjs} +266 -19
  265. package/dist/chunk-YZWE7XSM.js +5 -0
  266. package/dist/{chunk-I5IW3T2Y.js → chunk-Z3XSSF7B.js} +32 -15
  267. package/dist/{chunk-6UJMCWRY.js → chunk-Z4LIPMPM.js} +6 -0
  268. package/dist/chunk-ZASDSY7P.cjs +114 -0
  269. package/dist/{chunk-R33VKSH5.cjs → chunk-ZHJ7JGME.cjs} +11 -11
  270. package/dist/chunk-ZPD2AO3U.js +866 -0
  271. package/dist/{chunk-7UOUW76C.js → chunk-ZQAT5VT5.js} +101 -24
  272. package/dist/chunk-ZR46OJNZ.js +152 -0
  273. package/dist/{chunk-G3V4SFET.cjs → chunk-ZZ63NW7A.cjs} +78 -35
  274. package/dist/clear-33TWQ2ES.cjs +12 -0
  275. package/dist/clear-OFLFQ3MR.js +12 -0
  276. package/dist/{communityInstaller-6KCFN7YZ.js → communityInstaller-COB2KTOW.js} +9 -6
  277. package/dist/communityInstaller-TWMGPSYM.cjs +22 -0
  278. package/dist/completion-IIZMHXYP.cjs +17 -0
  279. package/dist/completion-PT4VM2H2.js +17 -0
  280. package/dist/config-KL6WU7R2.cjs +20 -0
  281. package/dist/{config-ZN66VXPS.js → config-R4O7GBTY.js} +7 -5
  282. package/dist/{constants-UFM5B232.js → constants-HVCHVQAF.js} +2 -2
  283. package/dist/constants-RLMJ5D5P.cjs +21 -0
  284. package/dist/{defaultHooks-RCXPHF4M.cjs → defaultHooks-2V2CQL63.cjs} +26 -11
  285. package/dist/{defaultHooks-RDRMER3Z.js → defaultHooks-TMHDU3FS.js} +26 -11
  286. package/dist/export-3PK3VFCE.js +15 -0
  287. package/dist/export-WLGNWEMJ.cjs +15 -0
  288. package/dist/{extractSessionMemories-V7K42ZHW.js → extractSessionMemories-A2JX5WJ2.js} +1 -1
  289. package/dist/{extractSessionMemories-SDW2MVBQ.cjs → extractSessionMemories-XL3MS37F.cjs} +1 -1
  290. package/dist/feedback-G635NCLJ.js +18 -0
  291. package/dist/feedback-LLMK3TZH.cjs +18 -0
  292. package/dist/fffSearchProvider-2YCNKOYD.js +412 -0
  293. package/dist/fffSearchProvider-W6627E2V.cjs +412 -0
  294. package/dist/filesystem-L6DQKGWK.js +11 -0
  295. package/dist/filesystem-PGUPCMVK.cjs +11 -0
  296. package/dist/{formatters-6K7QVWQL.cjs → formatters-53XTCNGQ.cjs} +1 -1
  297. package/dist/{formatters-DQHO5I36.js → formatters-T6KV4BPP.js} +1 -1
  298. package/dist/help-BAXLP2M2.cjs +12 -0
  299. package/dist/{help-2BLR7L43.js → help-X3OAZ3CY.js} +3 -3
  300. package/dist/history-6HOJSEMT.cjs +14 -0
  301. package/dist/{history-5FZ3M2AK.js → history-YKFPHBJN.js} +3 -3
  302. package/dist/hooks-7TA4PIIB.js +18 -0
  303. package/dist/hooks-XVFU67T2.cjs +18 -0
  304. package/dist/{i18n-K7QOWIBH.js → i18n-2KBUU7XL.js} +2 -2
  305. package/dist/i18n-MUJMKTFM.cjs +33 -0
  306. package/dist/ide-CCQ33PGC.cjs +15 -0
  307. package/dist/ide-VLVFBZ5F.js +15 -0
  308. package/dist/immediateCommandRouter-MTEHZXQX.js +15 -0
  309. package/dist/immediateCommandRouter-ROXU3MWT.cjs +15 -0
  310. package/dist/{import-UXM3VK7B.js → import-4CHYLS4K.js} +4 -4
  311. package/dist/{import-QEME3E4T.cjs → import-I7T4ZHYL.cjs} +4 -4
  312. package/dist/import-J46F54JY.cjs +10 -0
  313. package/dist/import-JWPYKXCZ.js +10 -0
  314. package/dist/index.cjs +747 -22356
  315. package/dist/index.d.cts +93 -0
  316. package/dist/index.d.ts +93 -0
  317. package/dist/index.js +786 -22395
  318. package/dist/init-262MWZV4.js +10 -0
  319. package/dist/init-EE5Y7RBL.cjs +10 -0
  320. package/dist/inkMode-VUE6ZDLD.cjs +7 -0
  321. package/dist/inkMode-WBNFOSAT.js +7 -0
  322. package/dist/inputPrompt-IIFKCX5Q.cjs +90 -0
  323. package/dist/inputPrompt-YGBHDUEP.js +90 -0
  324. package/dist/language-CVLPB7OV.js +21 -0
  325. package/dist/language-ZTWFHUSV.cjs +21 -0
  326. package/dist/learn-PON7I5QS.js +23 -0
  327. package/dist/learn-XLRSVNA3.cjs +23 -0
  328. package/dist/{lint-D5UOJWIK.cjs → lint-4NDGCSCL.cjs} +1 -1
  329. package/dist/{lint-NJPZWVN2.js → lint-FZ7ZJUB3.js} +1 -1
  330. package/dist/login-223QTGBG.cjs +26 -0
  331. package/dist/login-6IKTBUBY.js +26 -0
  332. package/dist/logout-RN2AG6SI.js +23 -0
  333. package/dist/logout-U3M4FFX7.cjs +23 -0
  334. package/dist/mcp-5O6PUL4G.js +20 -0
  335. package/dist/mcp-NUQ76QQB.cjs +20 -0
  336. package/dist/{mcp-install-VESN42PI.js → mcp-install-6XWXLFVY.js} +18 -11
  337. package/dist/{mcp-install-G27HSS3Z.cjs → mcp-install-P6DHES7V.cjs} +22 -15
  338. package/dist/memory-CYMDQ2YC.cjs +10 -0
  339. package/dist/memory-Q54CESNM.js +10 -0
  340. package/dist/{message-ZJ5AYAMT.cjs → message-4OKO775J.cjs} +1 -1
  341. package/dist/{message-JUBOK2VU.js → message-X3LOAAM7.js} +1 -1
  342. package/dist/model-6AJ77PJG.js +10 -0
  343. package/dist/model-IDRCKDML.cjs +10 -0
  344. package/dist/new-7LEWOUF2.cjs +12 -0
  345. package/dist/new-ZXHEWC2S.js +12 -0
  346. package/dist/onboarding-FXX7YHSJ.cjs +35 -0
  347. package/dist/onboarding-JYNMK6NI.js +35 -0
  348. package/dist/{patch-MOD7QC3D.cjs → patch-DJ2GPFST.cjs} +1 -1
  349. package/dist/{patch-5F6VBIT3.js → patch-NIJWIRHS.js} +1 -1
  350. package/dist/permissions-YBNSANIA.cjs +10 -0
  351. package/dist/permissions-YHJMVA6L.js +10 -0
  352. package/dist/plan-XEJMOT55.cjs +13 -0
  353. package/dist/plan-YYUAXPTL.js +13 -0
  354. package/dist/pr-review-CW6J7P62.cjs +9 -0
  355. package/dist/pr-review-YZSBQVT2.js +9 -0
  356. package/dist/quit-B43SJ6E4.cjs +10 -0
  357. package/dist/quit-GWTNHQSP.js +10 -0
  358. package/dist/rawMode-6W5AXAKI.cjs +7 -0
  359. package/dist/rawMode-GFNLXQPU.js +7 -0
  360. package/dist/{registry-KWZGYJC2.js → registry-34GL6BNJ.js} +30 -45
  361. package/dist/{registry-YN4FQPOO.cjs → registry-V24W7YK6.cjs} +66 -81
  362. package/dist/repeat-P4FAPE3Y.cjs +17 -0
  363. package/dist/repeat-RALE6AUO.js +17 -0
  364. package/dist/resume-DYVOQN5L.cjs +16 -0
  365. package/dist/resume-M25UQKOX.js +16 -0
  366. package/dist/review-QHP2KP4Q.js +9 -0
  367. package/dist/review-UWHWQHCB.cjs +9 -0
  368. package/dist/ripgrep-67SCU2BA.cjs +9 -0
  369. package/dist/ripgrep-VHJQQ55W.js +9 -0
  370. package/dist/rpc-NPS3PU4O.cjs +3730 -0
  371. package/dist/rpc-S3DGW6KV.js +3730 -0
  372. package/dist/search-CPX4PWHP.js +20 -0
  373. package/dist/search-VUF3M4N3.cjs +20 -0
  374. package/dist/{session-BSU2L5UI.cjs → session-LXKC4X5Q.cjs} +1 -1
  375. package/dist/{session-SZMRN5KG.js → session-NMMO4QOL.js} +1 -1
  376. package/dist/sessions-IYAXMK23.js +10 -0
  377. package/dist/sessions-JODKER5D.cjs +10 -0
  378. package/dist/settings-55BNW6BF.js +33 -0
  379. package/dist/settings-BKTS7OMC.cjs +33 -0
  380. package/dist/setup-IRC5HQG2.js +29 -0
  381. package/dist/setup-MMQ7TWOP.cjs +29 -0
  382. package/dist/share-6JRQECAH.cjs +17 -0
  383. package/dist/share-YM5MJKMO.js +17 -0
  384. package/dist/{skills-FYY6F2WV.cjs → skills-GGMZOVIE.cjs} +14 -11
  385. package/dist/skills-LWSOKOSH.cjs +29 -0
  386. package/dist/{skills-6OL4OSGA.js → skills-MVIZNHT4.js} +13 -10
  387. package/dist/skills-VWOMV3CR.js +29 -0
  388. package/dist/{skills-install-6CSWC24P.js → skills-install-QBA5RCV6.js} +22 -71
  389. package/dist/{skills-install-O3LZ2ETC.cjs → skills-install-VTAMCNNY.cjs} +35 -84
  390. package/dist/skills-new-GPL46YV2.js +18 -0
  391. package/dist/skills-new-L5BEZN5V.cjs +18 -0
  392. package/dist/slashCommands-FBPCIWM5.cjs +95 -0
  393. package/dist/slashCommands-FCWY5DXW.js +95 -0
  394. package/dist/status-3B5SDZPL.js +17 -0
  395. package/dist/status-TTGRF6NC.cjs +17 -0
  396. package/dist/summarizer-DGPHE5IQ.js +17 -0
  397. package/dist/summarizer-JNXLUAQG.cjs +17 -0
  398. package/dist/sync-77CXVVTK.cjs +21 -0
  399. package/dist/{sync-KWX67OUN.js → sync-7BILIQHP.js} +4 -4
  400. package/dist/sync-7OKF6636.js +21 -0
  401. package/dist/sync-EH4K5U3N.cjs +40 -0
  402. package/dist/{tasks-5FPBIFLC.js → tasks-R5MBGAQ6.js} +1 -1
  403. package/dist/{tasks-TXGKGNH6.cjs → tasks-V4WB3MFR.cjs} +1 -1
  404. package/dist/{team-5YXP3JGR.js → team-JESCHGWB.js} +1 -1
  405. package/dist/{team-IIWEZKNR.cjs → team-VQQKWGZB.cjs} +1 -1
  406. package/dist/{teammate-L6EZQ3I2.js → teammate-GZQSCIMS.js} +29 -8
  407. package/dist/{teammate-2KMKJXAM.cjs → teammate-J6PHGL23.cjs} +30 -9
  408. package/dist/theme-64BYGJ57.cjs +21 -0
  409. package/dist/theme-YJE6HEON.js +21 -0
  410. package/dist/tools-3PPTTKFV.js +9 -0
  411. package/dist/tools-THIQA7WC.cjs +9 -0
  412. package/dist/ui/questionModal.cjs +9 -6
  413. package/dist/ui/questionModal.js +8 -5
  414. package/dist/undo-PRTEGL2J.cjs +10 -0
  415. package/dist/undo-SZEHLX7X.js +10 -0
  416. package/dist/{update-TVAJMMBC.js → update-53WMKYVS.js} +1 -1
  417. package/dist/{update-Z6BIIQDC.cjs → update-NV6QRYY7.cjs} +1 -1
  418. package/dist/web-3BA2WV37.cjs +37 -0
  419. package/dist/web-6FYGBX5K.js +37 -0
  420. package/dist/workspaceSafety-MDJGHK6D.cjs +9 -0
  421. package/dist/workspaceSafety-XOUMUBVB.js +9 -0
  422. package/dist/yolo-GF2YD7ZI.js +9 -0
  423. package/dist/yolo-OGDA7HNC.cjs +9 -0
  424. package/dist/yoloMode-3DJDA75U.cjs +17 -0
  425. package/dist/yoloMode-4JOOSU26.js +17 -0
  426. package/package.json +46 -49
  427. package/dist/AgentRegistry-NQCLWABO.cjs +0 -10
  428. package/dist/CommunitySkillsCache-6QPRMTJO.js +0 -8
  429. package/dist/CommunitySkillsCache-GTQMOCCO.cjs +0 -8
  430. package/dist/GitHubRegistryFetcher-S7QFUEKV.cjs +0 -7
  431. package/dist/HookManager-Q2KYMCP4.cjs +0 -7
  432. package/dist/HookManager-TTP4Y6DC.js +0 -7
  433. package/dist/LearnAdvisor-A4Q5PPBI.js +0 -9
  434. package/dist/LearnAdvisor-GASQD7HT.cjs +0 -9
  435. package/dist/McpClientManager-RKD7C6OY.cjs +0 -8
  436. package/dist/MemoryManager-GUNLRP5S.js +0 -8
  437. package/dist/MemoryManager-TNSGKDKX.cjs +0 -8
  438. package/dist/PermissionManager-KMN53FJP.cjs +0 -11
  439. package/dist/ProviderFactory-MR5B23QJ.js +0 -9
  440. package/dist/ProviderFactory-VFGCJJX6.cjs +0 -9
  441. package/dist/SessionManager-FEUAU3ZJ.cjs +0 -10
  442. package/dist/SessionManager-IKWAK2PI.js +0 -10
  443. package/dist/SkillsRegistry-KPQFTRIT.cjs +0 -9
  444. package/dist/SkillsRegistry-XJSKPDF2.js +0 -9
  445. package/dist/SubAgent-NYH6GWQ3.js +0 -11
  446. package/dist/SubAgent-PZKBDUBA.cjs +0 -11
  447. package/dist/SyncApiClient-ZNYMT36M.cjs +0 -11
  448. package/dist/about-HHTF2YFL.js +0 -12
  449. package/dist/about-JGRVNNQC.cjs +0 -12
  450. package/dist/actionExecutor-U6IBN2TU.cjs +0 -19
  451. package/dist/actionExecutor-XT5FW3W6.js +0 -19
  452. package/dist/add-dir-247K3XRY.js +0 -10
  453. package/dist/add-dir-GS4DXKKH.cjs +0 -10
  454. package/dist/agents-R6ZEFTVR.cjs +0 -12
  455. package/dist/agents-WJPQWQF2.js +0 -12
  456. package/dist/agents-new-HKVEIBDJ.js +0 -14
  457. package/dist/agents-new-X6GTHIO6.cjs +0 -14
  458. package/dist/autoSkill-H4T6VVDA.cjs +0 -20
  459. package/dist/automode-BC6NVECO.js +0 -10
  460. package/dist/automode-WN2RSOGW.cjs +0 -10
  461. package/dist/chunk-33A755XB.cjs +0 -168
  462. package/dist/chunk-3OTU3RS3.cjs +0 -1607
  463. package/dist/chunk-4PKF7WPD.js +0 -100
  464. package/dist/chunk-ALYU6VTM.js +0 -105
  465. package/dist/chunk-AS6RTLN7.cjs +0 -203
  466. package/dist/chunk-BWN2CLLM.cjs +0 -298
  467. package/dist/chunk-HQ7YZKXE.js +0 -168
  468. package/dist/chunk-HVKOZ2VP.cjs +0 -115
  469. package/dist/chunk-J6QET7EF.cjs +0 -454
  470. package/dist/chunk-LWUJFGOZ.js +0 -115
  471. package/dist/chunk-P47WPOXN.js +0 -298
  472. package/dist/chunk-PRRCJFU3.cjs +0 -85
  473. package/dist/chunk-RO6WYEWH.js +0 -454
  474. package/dist/chunk-SYVYLZZF.cjs +0 -24
  475. package/dist/chunk-T73IDKDF.js +0 -111
  476. package/dist/chunk-YRLYSQEQ.cjs +0 -105
  477. package/dist/chunk-ZQE72E6W.cjs +0 -100
  478. package/dist/chunk-ZVY2XD6T.js +0 -1607
  479. package/dist/clear-UO4MNWZW.cjs +0 -12
  480. package/dist/clear-ZJ5NYP6E.js +0 -12
  481. package/dist/communityInstaller-PVSOFDZD.cjs +0 -19
  482. package/dist/completion-MMF2PN2H.js +0 -14
  483. package/dist/completion-UI5WKHXI.cjs +0 -14
  484. package/dist/config-E7RINK4R.cjs +0 -18
  485. package/dist/constants-6CPCJ3DY.cjs +0 -21
  486. package/dist/export-N4XIVDSL.cjs +0 -12
  487. package/dist/export-W22L4D5C.js +0 -12
  488. package/dist/feedback-DR6ADSNE.cjs +0 -15
  489. package/dist/feedback-FEEAP4QW.js +0 -15
  490. package/dist/filesystem-3SGCW2BF.js +0 -10
  491. package/dist/filesystem-MCFXJQ6R.cjs +0 -10
  492. package/dist/help-AQHGTS7P.cjs +0 -12
  493. package/dist/history-NIUDRMKA.cjs +0 -14
  494. package/dist/hooks-2EY4IPKV.js +0 -13
  495. package/dist/hooks-LJVORRIG.cjs +0 -13
  496. package/dist/i18n-ARDG2SMC.cjs +0 -33
  497. package/dist/ide-GFW6IJHD.js +0 -12
  498. package/dist/ide-N2ZNSSB3.cjs +0 -12
  499. package/dist/import-DFVN3KNZ.js +0 -10
  500. package/dist/import-ZS6DPGU5.cjs +0 -10
  501. package/dist/init-PY75HA3S.cjs +0 -10
  502. package/dist/init-QNMWLAVY.js +0 -10
  503. package/dist/language-5UE4G2BT.cjs +0 -18
  504. package/dist/language-UXMHEZUJ.js +0 -18
  505. package/dist/learn-HJ3FLNZC.cjs +0 -20
  506. package/dist/learn-MVYS3RU5.js +0 -20
  507. package/dist/localProjectPermissions-N77HA3XK.js +0 -18
  508. package/dist/localProjectPermissions-UFSMNTBJ.cjs +0 -18
  509. package/dist/login-DSE7H63A.js +0 -20
  510. package/dist/login-V3MEWPKN.cjs +0 -20
  511. package/dist/logout-BMVCLKKW.js +0 -18
  512. package/dist/logout-XEG7FHOZ.cjs +0 -18
  513. package/dist/mcp-PYUR4PHO.js +0 -18
  514. package/dist/mcp-SG6JFLGC.cjs +0 -18
  515. package/dist/memory-4ZMMEZ2Z.js +0 -10
  516. package/dist/memory-QSGMVVGH.cjs +0 -10
  517. package/dist/model-NANLBZ4Z.cjs +0 -10
  518. package/dist/model-ZXNV4AF7.js +0 -10
  519. package/dist/new-5QJY5JP2.js +0 -12
  520. package/dist/new-PMMG55UX.cjs +0 -12
  521. package/dist/permissions-LECTCJ4H.cjs +0 -13
  522. package/dist/permissions-VP5VGIBL.js +0 -13
  523. package/dist/plan-G5CEKJI4.js +0 -11
  524. package/dist/plan-QKOHE3LH.cjs +0 -11
  525. package/dist/quit-BKOOPHU5.cjs +0 -10
  526. package/dist/quit-FVFNYACP.js +0 -10
  527. package/dist/resume-EXFQSQPH.js +0 -13
  528. package/dist/resume-PP2IQM5S.cjs +0 -13
  529. package/dist/search-C56FBN67.cjs +0 -17
  530. package/dist/search-XGZDYBF4.js +0 -17
  531. package/dist/sessions-54KI3F2Q.js +0 -10
  532. package/dist/sessions-DDTSPNVW.cjs +0 -10
  533. package/dist/settings-BDO37TTO.cjs +0 -30
  534. package/dist/settings-FHRDFPLK.js +0 -30
  535. package/dist/share-IERCTBGN.cjs +0 -14
  536. package/dist/share-TGROUE6R.js +0 -14
  537. package/dist/skills-OM4IGBAA.cjs +0 -26
  538. package/dist/skills-S3GRN323.js +0 -26
  539. package/dist/skills-new-ALD2PTHN.js +0 -15
  540. package/dist/skills-new-PWLKK7GW.cjs +0 -15
  541. package/dist/slashCommands-L4ZD33LJ.js +0 -75
  542. package/dist/slashCommands-YY2VUUDF.cjs +0 -75
  543. package/dist/status-3PC5XWSS.cjs +0 -11
  544. package/dist/status-KCLVOYPD.js +0 -11
  545. package/dist/sync-6SDWG5RK.js +0 -18
  546. package/dist/sync-7JMZVEQD.cjs +0 -40
  547. package/dist/sync-WHURZL3U.cjs +0 -18
  548. package/dist/theme-BE5A4FPN.cjs +0 -18
  549. package/dist/theme-YMFCQP7J.js +0 -18
  550. package/dist/undo-KZHUUZTD.cjs +0 -10
  551. package/dist/undo-NEIEHQVX.js +0 -10
@@ -1,34 +1,46 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
2
2
 
3
- var _chunkJ6QET7EFcjs = require('./chunk-J6QET7EF.cjs');
3
+ var _chunkHXQREVTAcjs = require('./chunk-HXQREVTA.cjs');
4
4
 
5
5
 
6
6
  var _chunk4JNNTOGFcjs = require('./chunk-4JNNTOGF.cjs');
7
7
 
8
8
 
9
+ var _chunkDEQVRSV5cjs = require('./chunk-DEQVRSV5.cjs');
9
10
 
10
11
 
11
12
 
12
13
 
13
- var _chunkRKJTGGMUcjs = require('./chunk-RKJTGGMU.cjs');
14
+ var _chunkJ5HE6CUMcjs = require('./chunk-J5HE6CUM.cjs');
14
15
 
15
16
 
17
+ var _chunkWTB7AFL6cjs = require('./chunk-WTB7AFL6.cjs');
16
18
 
17
- var _chunkZYQMLKOKcjs = require('./chunk-ZYQMLKOK.cjs');
18
19
 
20
+ var _chunkWBU4Q4GScjs = require('./chunk-WBU4Q4GS.cjs');
19
21
 
20
22
 
23
+ var _chunkLFDPTJYFcjs = require('./chunk-LFDPTJYF.cjs');
21
24
 
22
- var _chunkPGRH5Q77cjs = require('./chunk-PGRH5Q77.cjs');
23
25
 
24
26
 
25
- var _chunkSEKD5FH3cjs = require('./chunk-SEKD5FH3.cjs');
26
27
 
27
28
 
28
- var _chunkULQ6MDSJcjs = require('./chunk-ULQ6MDSJ.cjs');
29
29
 
30
+ var _chunkWKRDBCP2cjs = require('./chunk-WKRDBCP2.cjs');
30
31
 
31
- var _chunkLJFUXC56cjs = require('./chunk-LJFUXC56.cjs');
32
+
33
+
34
+ var _chunkCH2J4PVEcjs = require('./chunk-CH2J4PVE.cjs');
35
+
36
+
37
+
38
+
39
+ var _chunk2VHB43IXcjs = require('./chunk-2VHB43IX.cjs');
40
+
41
+
42
+
43
+ var _chunkE26KKI46cjs = require('./chunk-E26KKI46.cjs');
32
44
 
33
45
  // src/core/actionExecutor.ts
34
46
  var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
@@ -515,8 +527,8 @@ function tokenize(code, language) {
515
527
  return tokens;
516
528
  }
517
529
  function colorToken(token) {
518
- if (_chunkPGRH5Q77cjs.isThemeInitialized.call(void 0, )) {
519
- const theme = _chunkPGRH5Q77cjs.getTheme.call(void 0, );
530
+ if (_chunk2VHB43IXcjs.isThemeInitialized.call(void 0, )) {
531
+ const theme = _chunk2VHB43IXcjs.getTheme.call(void 0, );
520
532
  switch (token.type) {
521
533
  case "keyword":
522
534
  return theme.fg("syntaxKeyword", token.value);
@@ -596,84 +608,6 @@ async function removeDependency(cwd, name, options = {}) {
596
608
  }
597
609
  }
598
610
 
599
- // src/actions/command.ts
600
- var _child_process = require('child_process');
601
-
602
- function runCommand(cmd, args, cwd, options = {}) {
603
- if (!cmd || typeof cmd !== "string") {
604
- return Promise.reject(new Error("Command is required and must be a string"));
605
- }
606
- return new Promise((resolve, reject) => {
607
- const workDir = options.directory ? _path.join.call(void 0, cwd, options.directory) : cwd;
608
- const spawnOptions = {
609
- cwd: workDir,
610
- shell: _nullishCoalesce(options.shell, () => ( false)),
611
- env: {
612
- ...process.env,
613
- AUTOHAND_CLI: "1",
614
- ...options.env
615
- }
616
- };
617
- if (options.background) {
618
- spawnOptions.detached = true;
619
- spawnOptions.stdio = ["ignore", "pipe", "pipe"];
620
- }
621
- let child;
622
- try {
623
- child = _child_process.spawn.call(void 0, cmd, args, spawnOptions);
624
- } catch (error) {
625
- const err = error;
626
- if (err.code === "ENOENT") {
627
- reject(new Error(`Command not found: ${cmd}`));
628
- } else {
629
- reject(error);
630
- }
631
- return;
632
- }
633
- if (options.background) {
634
- child.unref();
635
- resolve({
636
- stdout: "",
637
- stderr: "",
638
- code: null,
639
- backgroundPid: child.pid,
640
- signal: null
641
- });
642
- return;
643
- }
644
- let stdout = "";
645
- let stderr = "";
646
- let timeoutId;
647
- if (options.timeout && options.timeout > 0) {
648
- timeoutId = setTimeout(() => {
649
- child.kill("SIGTERM");
650
- }, options.timeout);
651
- }
652
- _optionalChain([child, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.on, 'call', _3 => _3("data", (chunk) => {
653
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
654
- stdout += text;
655
- _optionalChain([options, 'access', _4 => _4.onStdout, 'optionalCall', _5 => _5(text)]);
656
- })]);
657
- _optionalChain([child, 'access', _6 => _6.stderr, 'optionalAccess', _7 => _7.on, 'call', _8 => _8("data", (chunk) => {
658
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
659
- stderr += text;
660
- _optionalChain([options, 'access', _9 => _9.onStderr, 'optionalCall', _10 => _10(text)]);
661
- })]);
662
- child.once("error", (error) => {
663
- if (timeoutId) clearTimeout(timeoutId);
664
- if (error.code === "ENOENT") {
665
- reject(new Error(`Command not found: ${cmd}`));
666
- } else {
667
- reject(error);
668
- }
669
- });
670
- child.once("close", (code, signal) => {
671
- if (timeoutId) clearTimeout(timeoutId);
672
- resolve({ stdout, stderr, code, signal });
673
- });
674
- });
675
- }
676
-
677
611
  // src/actions/metadata.ts
678
612
  var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
679
613
 
@@ -684,12 +618,7 @@ async function listDirectoryTree(root, options = {}) {
684
618
  const maxEntries = _nullishCoalesce(options.maxEntries, () => ( 200));
685
619
  const workspaceRoot = _nullishCoalesce(options.workspaceRoot, () => ( root));
686
620
  const result = [];
687
- const resolvedRoot = _path2.default.resolve(root);
688
- const resolvedWorkspace = _path2.default.resolve(workspaceRoot);
689
- if (!resolvedRoot.startsWith(resolvedWorkspace)) {
690
- throw new Error(`Path ${root} is outside the workspace root.`);
691
- }
692
- const ignoreFilter = new (0, _chunkLJFUXC56cjs.GitIgnoreParser)(workspaceRoot);
621
+ const ignoreFilter = new (0, _chunkHXQREVTAcjs.GitIgnoreParser)(workspaceRoot);
693
622
  async function walk(current, prefix, currentDepth) {
694
623
  if (result.length >= maxEntries) {
695
624
  return;
@@ -755,7 +684,7 @@ async function checksumFile(root, relativePath, algorithm = "sha256") {
755
684
  }
756
685
 
757
686
  // src/actions/git.ts
758
-
687
+ var _child_process = require('child_process');
759
688
  var GIT_SAFETY = {
760
689
  /** Branches where force push is blocked */
761
690
  PROTECTED_BRANCHES: ["main", "master", "develop", "production", "staging"],
@@ -764,7 +693,7 @@ var GIT_SAFETY = {
764
693
  };
765
694
  function getCurrentBranch(cwd) {
766
695
  const result = _child_process.spawnSync.call(void 0, "git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8" });
767
- return _optionalChain([result, 'access', _11 => _11.stdout, 'optionalAccess', _12 => _12.trim, 'call', _13 => _13()]) || "";
696
+ return _optionalChain([result, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]) || "";
768
697
  }
769
698
  function getCommitsAhead(cwd, remote = "origin", branch) {
770
699
  const currentBranch = branch || getCurrentBranch(cwd);
@@ -773,7 +702,7 @@ function getCommitsAhead(cwd, remote = "origin", branch) {
773
702
  cwd,
774
703
  encoding: "utf8"
775
704
  });
776
- return parseInt(_optionalChain([result, 'access', _14 => _14.stdout, 'optionalAccess', _15 => _15.trim, 'call', _16 => _16()]) || "0", 10) || 0;
705
+ return parseInt(_optionalChain([result, 'access', _4 => _4.stdout, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]) || "0", 10) || 0;
777
706
  }
778
707
  function applyGitPatch(cwd, patch) {
779
708
  const result = _child_process.spawnSync.call(void 0, "git", ["apply", "-"], {
@@ -793,6 +722,13 @@ function diffFile(cwd, file) {
793
722
  }
794
723
  return result.stdout || "No diff";
795
724
  }
725
+ function diffWorkspace(cwd) {
726
+ const result = _child_process.spawnSync.call(void 0, "git", ["diff"], { cwd, encoding: "utf8" });
727
+ if (result.status !== 0) {
728
+ throw new Error(result.stderr || "git diff failed");
729
+ }
730
+ return result.stdout || "No diff";
731
+ }
796
732
  function checkoutFile(cwd, file) {
797
733
  const result = _child_process.spawnSync.call(void 0, "git", ["checkout", "--", file], { cwd, encoding: "utf8" });
798
734
  if (result.status !== 0) {
@@ -802,14 +738,22 @@ function checkoutFile(cwd, file) {
802
738
  function gitStatus(cwd) {
803
739
  const result = _child_process.spawnSync.call(void 0, "git", ["status", "-sb"], { cwd, encoding: "utf8" });
804
740
  if (result.status !== 0) {
805
- throw new Error(result.stderr || "git status failed");
741
+ const stderr = (result.stderr || "").trim();
742
+ if (stderr.includes("not a git repository")) {
743
+ return "This directory is not a git repository. You should call run_command with `git init` to initialize one, then retry.";
744
+ }
745
+ throw new Error(stderr || "git status failed");
806
746
  }
807
747
  return result.stdout || "clean";
808
748
  }
809
749
  function gitListUntracked(cwd) {
810
750
  const result = _child_process.spawnSync.call(void 0, "git", ["ls-files", "--others", "--exclude-standard"], { cwd, encoding: "utf8" });
811
751
  if (result.status !== 0) {
812
- throw new Error(result.stderr || "git ls-files failed");
752
+ const stderr = (result.stderr || "").trim();
753
+ if (stderr.includes("not a git repository")) {
754
+ return "This directory is not a git repository. You should call run_command with `git init` to initialize one, then retry.";
755
+ }
756
+ throw new Error(stderr || "git ls-files failed");
813
757
  }
814
758
  return result.stdout || "";
815
759
  }
@@ -821,7 +765,7 @@ function gitDiffRange(cwd, options = {}) {
821
765
  if (options.range) {
822
766
  args.push(options.range);
823
767
  }
824
- if (_optionalChain([options, 'access', _17 => _17.paths, 'optionalAccess', _18 => _18.length])) {
768
+ if (_optionalChain([options, 'access', _7 => _7.paths, 'optionalAccess', _8 => _8.length])) {
825
769
  args.push("--", ...options.paths);
826
770
  }
827
771
  const result = _child_process.spawnSync.call(void 0, "git", args, { cwd, encoding: "utf8" });
@@ -1120,7 +1064,7 @@ function getAutoCommitInfo(cwd) {
1120
1064
  diffSummary: ""
1121
1065
  };
1122
1066
  }
1123
- const changes = _optionalChain([statusResult, 'access', _19 => _19.stdout, 'optionalAccess', _20 => _20.trim, 'call', _21 => _21(), 'access', _22 => _22.split, 'call', _23 => _23("\n"), 'access', _24 => _24.filter, 'call', _25 => _25(Boolean)]) || [];
1067
+ const changes = _optionalChain([statusResult, 'access', _9 => _9.stdout, 'optionalAccess', _10 => _10.trim, 'call', _11 => _11(), 'access', _12 => _12.split, 'call', _13 => _13("\n"), 'access', _14 => _14.filter, 'call', _15 => _15(Boolean)]) || [];
1124
1068
  if (changes.length === 0) {
1125
1069
  return {
1126
1070
  canCommit: false,
@@ -1148,7 +1092,7 @@ function getAutoCommitInfo(cwd) {
1148
1092
  }
1149
1093
  }
1150
1094
  const diffStatResult = _child_process.spawnSync.call(void 0, "git", ["diff", "--stat", "HEAD"], { cwd, encoding: "utf8" });
1151
- const diffSummary = _optionalChain([diffStatResult, 'access', _26 => _26.stdout, 'optionalAccess', _27 => _27.trim, 'call', _28 => _28()]) || "";
1095
+ const diffSummary = _optionalChain([diffStatResult, 'access', _16 => _16.stdout, 'optionalAccess', _17 => _17.trim, 'call', _18 => _18()]) || "";
1152
1096
  const suggestedMessage = generateCommitMessage(added, modified, deleted, renamed);
1153
1097
  return {
1154
1098
  canCommit: true,
@@ -1203,7 +1147,7 @@ function generateCommitMessage(added, modified, deleted, renamed) {
1203
1147
  }
1204
1148
  function executeAutoCommit(cwd, message, stageAll = true) {
1205
1149
  const statusResult = _child_process.spawnSync.call(void 0, "git", ["status", "--porcelain"], { cwd, encoding: "utf8" });
1206
- const changes = _optionalChain([statusResult, 'access', _29 => _29.stdout, 'optionalAccess', _30 => _30.trim, 'call', _31 => _31(), 'access', _32 => _32.split, 'call', _33 => _33("\n"), 'access', _34 => _34.filter, 'call', _35 => _35(Boolean)]) || [];
1150
+ const changes = _optionalChain([statusResult, 'access', _19 => _19.stdout, 'optionalAccess', _20 => _20.trim, 'call', _21 => _21(), 'access', _22 => _22.split, 'call', _23 => _23("\n"), 'access', _24 => _24.filter, 'call', _25 => _25(Boolean)]) || [];
1207
1151
  if (stageAll) {
1208
1152
  const addResult = _child_process.spawnSync.call(void 0, "git", ["add", "-A"], { cwd, encoding: "utf8" });
1209
1153
  if (addResult.status !== 0) {
@@ -1223,7 +1167,7 @@ function executeAutoCommit(cwd, message, stageAll = true) {
1223
1167
  };
1224
1168
  }
1225
1169
  const hashResult = _child_process.spawnSync.call(void 0, "git", ["rev-parse", "--short", "HEAD"], { cwd, encoding: "utf8" });
1226
- const commitHash = _optionalChain([hashResult, 'access', _36 => _36.stdout, 'optionalAccess', _37 => _37.trim, 'call', _38 => _38()]);
1170
+ const commitHash = _optionalChain([hashResult, 'access', _26 => _26.stdout, 'optionalAccess', _27 => _27.trim, 'call', _28 => _28()]);
1227
1171
  return {
1228
1172
  success: true,
1229
1173
  message: `Committed ${changes.length} file(s): ${commitHash}`,
@@ -1351,6 +1295,9 @@ var DEFAULT_TEMPLATES = [
1351
1295
  }
1352
1296
  ];
1353
1297
  var WorktreeManager = class {
1298
+
1299
+
1300
+
1354
1301
  constructor(cwd) {
1355
1302
  this.repoRoot = this.findGitRoot(cwd);
1356
1303
  this.repoName = _path2.default.basename(this.repoRoot);
@@ -1434,7 +1381,7 @@ var WorktreeManager = class {
1434
1381
  if (result.status !== 0) {
1435
1382
  throw new Error(result.stderr || "Failed to create worktree");
1436
1383
  }
1437
- if (_optionalChain([template, 'optionalAccess', _39 => _39.setupCommands]) && options.runSetup !== false) {
1384
+ if (_optionalChain([template, 'optionalAccess', _29 => _29.setupCommands]) && options.runSetup !== false) {
1438
1385
  for (const cmd of template.setupCommands) {
1439
1386
  await this.runInWorktree(worktreePath, cmd);
1440
1387
  }
@@ -1448,7 +1395,7 @@ var WorktreeManager = class {
1448
1395
  const absolutePath = _path2.default.isAbsolute(worktreePath) ? worktreePath : _path2.default.resolve(this.repoRoot, worktreePath);
1449
1396
  const worktrees = this.list();
1450
1397
  const wt = worktrees.find((w) => w.path === absolutePath);
1451
- const branchToDelete = _optionalChain([wt, 'optionalAccess', _40 => _40.branch]);
1398
+ const branchToDelete = _optionalChain([wt, 'optionalAccess', _30 => _30.branch]);
1452
1399
  const args = ["worktree", "remove"];
1453
1400
  if (options.force) {
1454
1401
  args.push("--force");
@@ -1813,10 +1760,96 @@ var WorktreeManager = class {
1813
1760
  }
1814
1761
  };
1815
1762
 
1763
+ // src/actions/notebook.ts
1764
+ function createNotebookCell(cellType, source) {
1765
+ if (cellType === "code") {
1766
+ return {
1767
+ cell_type: "code",
1768
+ source,
1769
+ metadata: {},
1770
+ outputs: [],
1771
+ execution_count: null
1772
+ };
1773
+ }
1774
+ return {
1775
+ cell_type: "markdown",
1776
+ source,
1777
+ metadata: {}
1778
+ };
1779
+ }
1780
+ function resolveCellIndex(notebook, input) {
1781
+ if (typeof input.cell_index === "number") {
1782
+ return input.cell_index;
1783
+ }
1784
+ if (input.cell_id) {
1785
+ const index = notebook.cells.findIndex((cell) => cell.id === input.cell_id);
1786
+ if (index === -1) {
1787
+ throw new Error(`Notebook cell "${input.cell_id}" not found.`);
1788
+ }
1789
+ return index;
1790
+ }
1791
+ return -1;
1792
+ }
1793
+ function applyNotebookEdit(rawContent, input) {
1794
+ if (!input.path.endsWith(".ipynb")) {
1795
+ throw new Error("notebook_edit only supports .ipynb files.");
1796
+ }
1797
+ let notebook;
1798
+ try {
1799
+ notebook = JSON.parse(rawContent);
1800
+ } catch (e7) {
1801
+ throw new Error(`Notebook ${input.path} is not valid JSON.`);
1802
+ }
1803
+ if (!Array.isArray(notebook.cells)) {
1804
+ throw new Error(`Notebook ${input.path} does not contain a valid cells array.`);
1805
+ }
1806
+ const editMode = _nullishCoalesce(input.edit_mode, () => ( "replace"));
1807
+ const index = resolveCellIndex(notebook, input);
1808
+ if (editMode === "insert") {
1809
+ if (!input.cell_type) {
1810
+ throw new Error('notebook_edit insert requires "cell_type".');
1811
+ }
1812
+ if (typeof input.new_source !== "string") {
1813
+ throw new Error('notebook_edit insert requires "new_source".');
1814
+ }
1815
+ const insertAt = index >= 0 ? index + 1 : notebook.cells.length;
1816
+ notebook.cells.splice(insertAt, 0, createNotebookCell(input.cell_type, input.new_source));
1817
+ return {
1818
+ updated: `${JSON.stringify(notebook, null, 2)}
1819
+ `,
1820
+ summary: `Inserted notebook cell at index ${insertAt} in ${input.path}.`
1821
+ };
1822
+ }
1823
+ if (index < 0 || index >= notebook.cells.length) {
1824
+ throw new Error('notebook_edit requires a valid "cell_index" or "cell_id".');
1825
+ }
1826
+ if (editMode === "delete") {
1827
+ notebook.cells.splice(index, 1);
1828
+ return {
1829
+ updated: `${JSON.stringify(notebook, null, 2)}
1830
+ `,
1831
+ summary: `Deleted notebook cell ${index} in ${input.path}.`
1832
+ };
1833
+ }
1834
+ if (typeof input.new_source !== "string") {
1835
+ throw new Error('notebook_edit replace requires "new_source".');
1836
+ }
1837
+ const target = notebook.cells[index];
1838
+ target.source = input.new_source;
1839
+ if (input.cell_type) {
1840
+ target.cell_type = input.cell_type;
1841
+ }
1842
+ return {
1843
+ updated: `${JSON.stringify(notebook, null, 2)}
1844
+ `,
1845
+ summary: `Updated notebook cell ${index} in ${input.path}.`
1846
+ };
1847
+ }
1848
+
1816
1849
  // src/core/customCommands.ts
1817
1850
 
1818
1851
 
1819
- var COMMANDS_DIR = _chunkSEKD5FH3cjs.AUTOHAND_PATHS.commands;
1852
+ var COMMANDS_DIR = _chunkE26KKI46cjs.AUTOHAND_PATHS.commands;
1820
1853
  async function loadCustomCommand(name) {
1821
1854
  const filePath = _path2.default.join(COMMANDS_DIR, `${sanitizeName(name)}.json`);
1822
1855
  if (!await _fsextra2.default.pathExists(filePath)) {
@@ -1956,7 +1989,7 @@ async function fetchGitHubInfo(parsed) {
1956
1989
  stars: data.stargazers_count,
1957
1990
  language: data.language,
1958
1991
  defaultBranch: data.default_branch,
1959
- license: _optionalChain([data, 'access', _41 => _41.license, 'optionalAccess', _42 => _42.spdx_id]) || null
1992
+ license: _optionalChain([data, 'access', _31 => _31.license, 'optionalAccess', _32 => _32.spdx_id]) || null
1960
1993
  };
1961
1994
  }
1962
1995
  async function fetchGitLabInfo(parsed) {
@@ -2190,16 +2223,245 @@ async function webRepo(options) {
2190
2223
  }
2191
2224
  }
2192
2225
 
2226
+ // src/actions/projectTracker.ts
2227
+
2228
+ var ISSUE_LIST_FIELDS = "number,title,state,assignees,labels,createdAt,url";
2229
+ var ISSUE_VIEW_FIELDS = "number,title,state,body,assignees,labels,comments,createdAt,milestone,author,url";
2230
+ var PR_LIST_FIELDS = "number,title,state,author,baseRefName,headRefName,labels,createdAt,isDraft,url";
2231
+ var PR_VIEW_FIELDS = "number,title,state,body,author,baseRefName,headRefName,labels,comments,latestReviews,statusCheckRollup,mergeable,additions,deletions,createdAt,isDraft,url";
2232
+ async function runGh(args) {
2233
+ return new Promise((resolve, reject) => {
2234
+ _child_process.execFile.call(void 0, "gh", args, {
2235
+ timeout: 3e4,
2236
+ maxBuffer: 5 * 1024 * 1024
2237
+ // 5MB
2238
+ }, (err, stdout, stderr) => {
2239
+ if (!err) {
2240
+ resolve(stdout);
2241
+ return;
2242
+ }
2243
+ const error = err;
2244
+ if (error.code === "ENOENT" || _optionalChain([error, 'access', _33 => _33.message, 'optionalAccess', _34 => _34.includes, 'call', _35 => _35("command not found")])) {
2245
+ reject(new Error("gh CLI is not installed. Install it from https://cli.github.com"));
2246
+ return;
2247
+ }
2248
+ const errMsg = stderr || error.message || "Unknown error";
2249
+ if (errMsg.includes("auth login") || errMsg.includes("not logged")) {
2250
+ reject(new Error("gh CLI is not authenticated. Run 'gh auth login' first."));
2251
+ return;
2252
+ }
2253
+ reject(new Error(`gh command failed: ${errMsg.trim()}`));
2254
+ });
2255
+ });
2256
+ }
2257
+ async function projectTracker(action) {
2258
+ if (action.action === "get_issue" || action.action === "get_pr") {
2259
+ if (action.number == null) {
2260
+ return `Error: The 'number' parameter is required for ${action.action}`;
2261
+ }
2262
+ if (!Number.isInteger(action.number) || action.number <= 0) {
2263
+ return `Error: The 'number' parameter must be a positive integer`;
2264
+ }
2265
+ }
2266
+ if (action.state === "merged" && action.action === "list_issues") {
2267
+ return `Error: The 'merged' state is only valid for list_prs`;
2268
+ }
2269
+ try {
2270
+ switch (action.action) {
2271
+ case "list_issues":
2272
+ return await listIssues(action);
2273
+ case "get_issue":
2274
+ return await getIssue(action);
2275
+ case "list_prs":
2276
+ return await listPrs(action);
2277
+ case "get_pr":
2278
+ return await getPr(action);
2279
+ case "get_user":
2280
+ return await getUser();
2281
+ default:
2282
+ return `Error: Unknown action: ${action.action}. Valid actions: list_issues, get_issue, list_prs, get_pr, get_user`;
2283
+ }
2284
+ } catch (err) {
2285
+ return `Error: ${err instanceof Error ? err.message : String(err)}`;
2286
+ }
2287
+ }
2288
+ async function listIssues(action) {
2289
+ const args = ["issue", "list", "--json", ISSUE_LIST_FIELDS];
2290
+ args.push("--limit", String(_nullishCoalesce(action.limit, () => ( 20))));
2291
+ if (action.state) args.push("--state", action.state);
2292
+ if (action.assignee) args.push("--assignee", action.assignee);
2293
+ if (action.labels) args.push("--label", action.labels);
2294
+ if (action.repo) args.push("-R", action.repo);
2295
+ return runGh(args);
2296
+ }
2297
+ async function getIssue(action) {
2298
+ const args = ["issue", "view", String(action.number), "--json", ISSUE_VIEW_FIELDS];
2299
+ if (action.repo) args.push("-R", action.repo);
2300
+ return runGh(args);
2301
+ }
2302
+ async function listPrs(action) {
2303
+ const args = ["pr", "list", "--json", PR_LIST_FIELDS];
2304
+ args.push("--limit", String(_nullishCoalesce(action.limit, () => ( 20))));
2305
+ if (action.state) args.push("--state", action.state);
2306
+ if (action.author) args.push("--author", action.author);
2307
+ if (action.base) args.push("--base", action.base);
2308
+ if (action.labels) args.push("--label", action.labels);
2309
+ if (action.repo) args.push("-R", action.repo);
2310
+ return runGh(args);
2311
+ }
2312
+ async function getPr(action) {
2313
+ const args = ["pr", "view", String(action.number), "--json", PR_VIEW_FIELDS];
2314
+ if (action.repo) args.push("-R", action.repo);
2315
+ return runGh(args);
2316
+ }
2317
+ async function getUser() {
2318
+ try {
2319
+ const stdout = await runGh(["api", "user", "--jq", ".login"]);
2320
+ return `Authenticated as: ${stdout.trim()}`;
2321
+ } catch (err) {
2322
+ const msg = err instanceof Error ? err.message : String(err);
2323
+ if (msg.includes("not installed") || msg.includes("not authenticated")) {
2324
+ throw err;
2325
+ }
2326
+ throw new Error("Failed to get GitHub user. Ensure gh is authenticated: run 'gh auth status'");
2327
+ }
2328
+ }
2329
+
2193
2330
  // src/core/toolsRegistry.ts
2194
2331
 
2332
+ var _promises = require('fs/promises'); var _promises2 = _interopRequireDefault(_promises);
2333
+
2334
+
2335
+ // src/core/metaTools/schema.ts
2336
+
2337
+ var _zod = require('zod');
2338
+ var META_TOOL_SCHEMA_VERSION = 1;
2339
+ var META_TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]*$/;
2340
+ var META_TOOL_SCOPES = ["user", "project"];
2341
+ var JsonSchemaObject = _zod.z.record(_zod.z.string(), _zod.z.unknown()).refine((value) => value.type === "object", 'parameters must be a JSON Schema object with type "object"');
2342
+ var MetaToolCreateInputSchema = _zod.z.object({
2343
+ name: _zod.z.string().trim().regex(META_TOOL_NAME_PATTERN, "name must be snake_case and start with a lowercase letter"),
2344
+ description: _zod.z.string().trim().min(1).max(300),
2345
+ parameters: JsonSchemaObject,
2346
+ handler: _zod.z.string().trim().min(1).max(2e3),
2347
+ source: _zod.z.enum(["agent", "user"]).default("agent"),
2348
+ scope: _zod.z.enum(META_TOOL_SCOPES).default("user")
2349
+ });
2350
+ var MetaToolDefinitionSchema = MetaToolCreateInputSchema.extend({
2351
+ schemaVersion: _zod.z.literal(META_TOOL_SCHEMA_VERSION),
2352
+ createdAt: _zod.z.string().min(1),
2353
+ updatedAt: _zod.z.string().min(1).optional(),
2354
+ fingerprint: _zod.z.string().min(16),
2355
+ disabled: _zod.z.boolean().optional()
2356
+ });
2357
+ function canonicalize(value) {
2358
+ if (Array.isArray(value)) {
2359
+ return `[${value.map(canonicalize).join(",")}]`;
2360
+ }
2361
+ if (value && typeof value === "object") {
2362
+ const record = value;
2363
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalize(record[key])}`).join(",")}}`;
2364
+ }
2365
+ return JSON.stringify(value);
2366
+ }
2367
+ function fingerprintMetaTool(input) {
2368
+ return _crypto.createHash.call(void 0, "sha256").update(canonicalize({
2369
+ name: input.name,
2370
+ description: input.description,
2371
+ parameters: input.parameters,
2372
+ handler: input.handler
2373
+ })).digest("hex");
2374
+ }
2375
+ function normalizeMetaToolDefinition(candidate) {
2376
+ if (!candidate || typeof candidate !== "object") {
2377
+ return null;
2378
+ }
2379
+ const value = candidate;
2380
+ const source = value.source === "user" ? "user" : "agent";
2381
+ const scope = value.scope === "project" ? "project" : "user";
2382
+ const definition = {
2383
+ ...value,
2384
+ schemaVersion: _nullishCoalesce(value.schemaVersion, () => ( META_TOOL_SCHEMA_VERSION)),
2385
+ source,
2386
+ scope,
2387
+ createdAt: typeof value.createdAt === "string" ? value.createdAt : (/* @__PURE__ */ new Date(0)).toISOString()
2388
+ };
2389
+ const parsedCreateInput = MetaToolCreateInputSchema.safeParse(definition);
2390
+ if (!parsedCreateInput.success) {
2391
+ return null;
2392
+ }
2393
+ const parsed = MetaToolDefinitionSchema.safeParse({
2394
+ ...definition,
2395
+ fingerprint: typeof value.fingerprint === "string" ? value.fingerprint : fingerprintMetaTool(parsedCreateInput.data)
2396
+ });
2397
+ return parsed.success ? parsed.data : null;
2398
+ }
2399
+
2400
+ // src/core/metaTools/safety.ts
2401
+ var DANGEROUS_PATTERNS = [
2402
+ { pattern: /rm\s+(-[rf]+\s+)*\/(?!\w)/i, description: "rm with root path" },
2403
+ { pattern: /rm\s+.*--no-preserve-root/i, description: "rm --no-preserve-root" },
2404
+ { pattern: /dd\s+.*(?:of|if)=\/dev\/[sh]d/i, description: "dd to disk device" },
2405
+ { pattern: /mkfs\./i, description: "filesystem format" },
2406
+ { pattern: /wipefs/i, description: "disk wipe" },
2407
+ { pattern: /\bsudo\s/i, description: "sudo command" },
2408
+ { pattern: /\bsu\s+-?\s*\w/i, description: "su command" },
2409
+ { pattern: /chmod\s+[0-7]*7[0-7]*/i, description: "world-writable chmod" },
2410
+ { pattern: /chown\s+root/i, description: "chown to root" },
2411
+ { pattern: /curl\s+.*\|\s*(ba)?sh/i, description: "curl | bash" },
2412
+ { pattern: /wget\s+.*\|\s*(ba)?sh/i, description: "wget | sh" },
2413
+ { pattern: /\beval\s+[`$]/i, description: "eval with expansion" },
2414
+ { pattern: /:\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;/i, description: "fork bomb" },
2415
+ { pattern: /while\s+true.*do.*done/i, description: "infinite loop" },
2416
+ { pattern: /nc\s+.*-e\s*\/bin/i, description: "netcat reverse shell" },
2417
+ { pattern: /ncat\s+.*-e\s*\/bin/i, description: "ncat reverse shell" },
2418
+ { pattern: /bash\s+-i\s+>&?\s*\/dev\/tcp/i, description: "bash reverse shell" },
2419
+ { pattern: /iptables\s+-F/i, description: "flush firewall rules" },
2420
+ { pattern: /gpg\s+.*--encrypt.*-r\s+\S+\s+\//i, description: "gpg encrypt root" }
2421
+ ];
2422
+ function assertSafeMetaToolHandler(handler) {
2423
+ for (const { pattern, description } of DANGEROUS_PATTERNS) {
2424
+ if (pattern.test(handler)) {
2425
+ throw new Error(`Handler contains dangerous pattern: ${description}`);
2426
+ }
2427
+ }
2428
+ }
2195
2429
 
2196
- var ToolsRegistry = class {
2197
- constructor(toolsDir = _chunkSEKD5FH3cjs.AUTOHAND_PATHS.tools) {
2198
- this.toolsDir = toolsDir;
2199
- this.metaToolCache = /* @__PURE__ */ new Map();
2430
+ // src/core/toolsRegistry.ts
2431
+ function locationKey(scope, name) {
2432
+ return `${scope}:${name}`;
2433
+ }
2434
+ function normalizeLocations(input) {
2435
+ if (Array.isArray(input)) {
2436
+ return input;
2200
2437
  }
2438
+ return [{ scope: "user", dir: _nullishCoalesce(input, () => ( _chunkE26KKI46cjs.AUTOHAND_PATHS.tools)) }];
2439
+ }
2440
+ function delay(ms) {
2441
+ return new Promise((resolve) => setTimeout(resolve, ms));
2442
+ }
2443
+ function createToolsRegistry(workspaceRoot, userToolsDir = _chunkE26KKI46cjs.AUTOHAND_PATHS.tools) {
2444
+ const locations = workspaceRoot ? [
2445
+ { scope: "project", dir: _path2.default.join(workspaceRoot, _chunkE26KKI46cjs.PROJECT_DIR_NAME, "tools") },
2446
+ { scope: "user", dir: userToolsDir }
2447
+ ] : [{ scope: "user", dir: userToolsDir }];
2448
+ return new ToolsRegistry(locations);
2449
+ }
2450
+ var ToolsRegistry = (_class = class {
2451
+ __init() {this.metaToolCache = /* @__PURE__ */ new Map()}
2452
+ __init2() {this.metaToolRecords = /* @__PURE__ */ new Map()}
2453
+ __init3() {this.diagnostics = []}
2454
+ constructor(locations) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
2455
+ this.locations = normalizeLocations(locations);
2456
+ }
2457
+
2201
2458
  async initialize() {
2202
- await _fsextra2.default.ensureDir(this.toolsDir);
2459
+ this.metaToolCache.clear();
2460
+ this.metaToolRecords.clear();
2461
+ this.diagnostics = [];
2462
+ for (const location of this.locations) {
2463
+ await _fsextra2.default.ensureDir(location.dir);
2464
+ }
2203
2465
  await this.loadMetaToolDefinitions();
2204
2466
  }
2205
2467
  async listTools(builtIns) {
@@ -2225,20 +2487,41 @@ var ToolsRegistry = class {
2225
2487
  entries.push({
2226
2488
  name: tool.name,
2227
2489
  description: tool.description,
2228
- source: "meta"
2490
+ source: "meta",
2491
+ scope: tool.scope,
2492
+ disabled: tool.disabled,
2493
+ createdAt: tool.createdAt,
2494
+ schemaVersion: tool.schemaVersion,
2495
+ handlerPreview: tool.handler.length > 140 ? `${tool.handler.slice(0, 137)}...` : tool.handler,
2496
+ reuseHint: `Use ${tool.name} instead of creating another tool for: ${tool.description}`
2229
2497
  });
2230
2498
  seen.add(name);
2231
2499
  }
2232
2500
  return entries;
2233
2501
  }
2234
2502
  async saveMetaTool(definition) {
2235
- const fullDef = {
2236
- ...definition,
2237
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
2238
- };
2239
- const filePath = _path2.default.join(this.toolsDir, `${definition.name}.json`);
2240
- await _fsextra2.default.writeJson(filePath, fullDef, { spaces: 2 });
2241
- this.metaToolCache.set(definition.name, fullDef);
2503
+ const fullDef = normalizeMetaToolDefinition(definition);
2504
+ if (!fullDef) {
2505
+ throw new Error(`Invalid meta-tool definition for "${definition.name}"`);
2506
+ }
2507
+ assertSafeMetaToolHandler(fullDef.handler);
2508
+ const location = this.getLocationForScope(fullDef.scope);
2509
+ const filePath = _path2.default.join(location.dir, `${fullDef.name}.json`);
2510
+ const release = await this.acquireLock(location.dir, fullDef.name);
2511
+ try {
2512
+ const existing = await this.readDefinition(filePath);
2513
+ if (existing) {
2514
+ if (existing.fingerprint === fullDef.fingerprint) {
2515
+ this.upsertRecord(existing, filePath);
2516
+ return existing;
2517
+ }
2518
+ throw new Error(`Meta-tool "${fullDef.name}" already exists in ${fullDef.scope} scope`);
2519
+ }
2520
+ await this.writeDefinition(filePath, fullDef);
2521
+ } finally {
2522
+ await release();
2523
+ }
2524
+ this.upsertRecord(fullDef, filePath);
2242
2525
  return fullDef;
2243
2526
  }
2244
2527
  getMetaTool(name) {
@@ -2250,6 +2533,71 @@ var ToolsRegistry = class {
2250
2533
  getAllMetaTools() {
2251
2534
  return Array.from(this.metaToolCache.values());
2252
2535
  }
2536
+ listMetaTools(options = {}) {
2537
+ if (!options.includeDisabled) {
2538
+ return this.getAllMetaTools();
2539
+ }
2540
+ return Array.from(this.metaToolRecords.values()).map((record) => record.definition);
2541
+ }
2542
+ getDiagnostics() {
2543
+ return [...this.diagnostics];
2544
+ }
2545
+ async deleteMetaTool(name, scope) {
2546
+ const record = this.findRecord(name, scope);
2547
+ if (!record) {
2548
+ throw new Error(`Meta-tool "${name}" not found`);
2549
+ }
2550
+ await _fsextra2.default.remove(record.filePath);
2551
+ this.deleteRecord(record.definition);
2552
+ return record.definition;
2553
+ }
2554
+ async setMetaToolDisabled(name, disabled, scope) {
2555
+ const record = this.findRecord(name, scope);
2556
+ if (!record) {
2557
+ throw new Error(`Meta-tool "${name}" not found`);
2558
+ }
2559
+ const updated = {
2560
+ ...record.definition,
2561
+ disabled,
2562
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2563
+ };
2564
+ await this.writeDefinition(record.filePath, updated);
2565
+ this.upsertRecord(updated, record.filePath);
2566
+ this.rebuildActiveCache();
2567
+ return updated;
2568
+ }
2569
+ async renameMetaTool(name, newName, scope) {
2570
+ if (!META_TOOL_NAME_PATTERN.test(newName)) {
2571
+ throw new Error("new name must be snake_case and start with a lowercase letter");
2572
+ }
2573
+ const record = this.findRecord(name, scope);
2574
+ if (!record) {
2575
+ throw new Error(`Meta-tool "${name}" not found`);
2576
+ }
2577
+ if (this.findRecord(newName)) {
2578
+ throw new Error(`Meta-tool "${newName}" already exists`);
2579
+ }
2580
+ const renamed = {
2581
+ ...record.definition,
2582
+ name: newName,
2583
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2584
+ };
2585
+ const normalized = normalizeMetaToolDefinition({
2586
+ ...renamed,
2587
+ fingerprint: fingerprintMetaTool(renamed)
2588
+ });
2589
+ if (!normalized) {
2590
+ throw new Error(`Invalid meta-tool definition for "${newName}"`);
2591
+ }
2592
+ const location = this.getLocationForScope(normalized.scope);
2593
+ const nextFilePath = _path2.default.join(location.dir, `${newName}.json`);
2594
+ await this.writeDefinition(nextFilePath, normalized);
2595
+ await _fsextra2.default.remove(record.filePath);
2596
+ this.deleteRecord(record.definition);
2597
+ this.upsertRecord(normalized, nextFilePath);
2598
+ this.rebuildActiveCache();
2599
+ return normalized;
2600
+ }
2253
2601
  toToolDefinitions() {
2254
2602
  return this.getAllMetaTools().map((tool) => {
2255
2603
  const params = tool.parameters;
@@ -2265,163 +2613,375 @@ var ToolsRegistry = class {
2265
2613
  });
2266
2614
  }
2267
2615
  async loadMetaToolDefinitions() {
2268
- try {
2269
- const exists = await _fsextra2.default.pathExists(this.toolsDir);
2270
- if (!exists) {
2271
- return;
2272
- }
2273
- const files = await _fsextra2.default.readdir(this.toolsDir);
2274
- for (const file of files) {
2275
- if (!file.endsWith(".json")) {
2616
+ for (const location of this.locations) {
2617
+ try {
2618
+ const exists = await _fsextra2.default.pathExists(location.dir);
2619
+ if (!exists) {
2276
2620
  continue;
2277
2621
  }
2278
- const fullPath = _path2.default.join(this.toolsDir, file);
2279
- try {
2280
- const data = await _fsextra2.default.readJson(fullPath);
2281
- if (this.isValidMetaTool(data)) {
2282
- this.metaToolCache.set(data.name, data);
2622
+ const files = await _fsextra2.default.readdir(location.dir);
2623
+ for (const file of files) {
2624
+ if (!file.endsWith(".json")) {
2625
+ continue;
2626
+ }
2627
+ const fullPath = _path2.default.join(location.dir, file);
2628
+ try {
2629
+ const data = normalizeMetaToolDefinition({
2630
+ ...await _fsextra2.default.readJson(fullPath),
2631
+ scope: location.scope
2632
+ });
2633
+ if (data) {
2634
+ assertSafeMetaToolHandler(data.handler);
2635
+ this.metaToolRecords.set(locationKey(data.scope, data.name), { definition: data, filePath: fullPath });
2636
+ } else {
2637
+ this.diagnostics.push({ file: fullPath, reason: "invalid meta-tool definition" });
2638
+ }
2639
+ } catch (error) {
2640
+ const reason = error instanceof Error ? error.message : "invalid meta-tool file";
2641
+ this.diagnostics.push({ file: fullPath, reason });
2283
2642
  }
2284
- } catch (e7) {
2285
2643
  }
2644
+ } catch (error) {
2645
+ const reason = error instanceof Error ? error.message : "tools directory could not be read";
2646
+ this.diagnostics.push({ file: location.dir, reason });
2286
2647
  }
2287
- } catch (e8) {
2288
2648
  }
2649
+ this.rebuildActiveCache();
2289
2650
  }
2290
- isValidMetaTool(candidate) {
2291
- if (!candidate || typeof candidate !== "object") {
2292
- return false;
2651
+ getLocationForScope(scope) {
2652
+ const location = this.locations.find((candidate) => candidate.scope === scope);
2653
+ if (!location) {
2654
+ throw new Error(`No tools directory configured for ${scope} scope`);
2293
2655
  }
2294
- const value = candidate;
2295
- return typeof value.name === "string" && typeof value.description === "string" && typeof value.handler === "string" && typeof value.parameters === "object";
2656
+ return location;
2296
2657
  }
2297
- };
2658
+ async readDefinition(filePath) {
2659
+ if (!await _fsextra2.default.pathExists(filePath)) {
2660
+ return null;
2661
+ }
2662
+ return normalizeMetaToolDefinition(await _fsextra2.default.readJson(filePath));
2663
+ }
2664
+ async writeDefinition(filePath, definition) {
2665
+ const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
2666
+ try {
2667
+ await _fsextra2.default.ensureDir(_path2.default.dirname(filePath));
2668
+ await _fsextra2.default.outputFile(tempPath, `${JSON.stringify(definition, null, 2)}
2669
+ `, { mode: 384 });
2670
+ const handle = await _promises2.default.open(tempPath, "r");
2671
+ try {
2672
+ await handle.sync();
2673
+ } finally {
2674
+ await handle.close();
2675
+ }
2676
+ await _promises2.default.rename(tempPath, filePath);
2677
+ } catch (error) {
2678
+ await _fsextra2.default.remove(tempPath).catch(() => {
2679
+ });
2680
+ throw error;
2681
+ }
2682
+ }
2683
+ async acquireLock(dir, name) {
2684
+ await _fsextra2.default.ensureDir(dir);
2685
+ const lockPath = _path2.default.join(dir, `${name}.lock`);
2686
+ for (let attempt = 0; attempt < 40; attempt++) {
2687
+ try {
2688
+ const handle = await _promises2.default.open(lockPath, "wx", 384);
2689
+ await handle.close();
2690
+ return async () => {
2691
+ await _fsextra2.default.remove(lockPath).catch(() => {
2692
+ });
2693
+ };
2694
+ } catch (error) {
2695
+ const code = typeof error === "object" && error && "code" in error ? error.code : void 0;
2696
+ if (code === "EEXIST") {
2697
+ await delay(25);
2698
+ continue;
2699
+ }
2700
+ throw error;
2701
+ }
2702
+ }
2703
+ throw new Error(`Timed out waiting for meta-tool lock "${name}"`);
2704
+ }
2705
+ upsertRecord(definition, filePath) {
2706
+ this.metaToolRecords.set(locationKey(definition.scope, definition.name), { definition, filePath });
2707
+ this.rebuildActiveCache();
2708
+ }
2709
+ deleteRecord(definition) {
2710
+ this.metaToolRecords.delete(locationKey(definition.scope, definition.name));
2711
+ this.rebuildActiveCache();
2712
+ }
2713
+ findRecord(name, scope) {
2714
+ if (scope) {
2715
+ return this.metaToolRecords.get(locationKey(scope, name));
2716
+ }
2717
+ for (const location of this.locations) {
2718
+ const record = this.metaToolRecords.get(locationKey(location.scope, name));
2719
+ if (record) {
2720
+ return record;
2721
+ }
2722
+ }
2723
+ return void 0;
2724
+ }
2725
+ rebuildActiveCache() {
2726
+ this.metaToolCache.clear();
2727
+ for (const location of this.locations) {
2728
+ for (const record of this.metaToolRecords.values()) {
2729
+ if (record.definition.scope !== location.scope || record.definition.disabled) {
2730
+ continue;
2731
+ }
2732
+ if (!this.metaToolCache.has(record.definition.name)) {
2733
+ this.metaToolCache.set(record.definition.name, record.definition);
2734
+ }
2735
+ }
2736
+ }
2737
+ }
2738
+ }, _class);
2298
2739
 
2299
- // src/core/SecurityScanner.ts
2300
- var SecurityScanner = class {
2301
- constructor() {
2302
- /**
2303
- * Built-in secret detection patterns
2304
- */
2305
- this.patterns = [
2306
- // AWS
2307
- {
2308
- name: "AWS Access Key",
2309
- regex: /AKIA[0-9A-Z]{16}/,
2310
- severity: "high",
2311
- description: "AWS Access Key ID"
2312
- },
2313
- // GitHub
2314
- {
2315
- name: "GitHub Token",
2316
- regex: /ghp_[a-zA-Z0-9]{36}/,
2317
- severity: "high",
2318
- description: "GitHub Personal Access Token"
2319
- },
2320
- {
2321
- name: "GitHub OAuth",
2322
- regex: /gho_[a-zA-Z0-9]{36}/,
2323
- severity: "high",
2324
- description: "GitHub OAuth Token"
2325
- },
2326
- {
2327
- name: "GitHub App Token",
2328
- regex: /ghu_[a-zA-Z0-9]{36}/,
2329
- severity: "high",
2330
- description: "GitHub App User Token"
2331
- },
2332
- // OpenAI / Anthropic
2333
- {
2334
- name: "OpenAI Key",
2335
- regex: /sk-proj-[a-zA-Z0-9]{32,}/,
2336
- severity: "high",
2337
- description: "OpenAI Project API Key"
2338
- },
2339
- {
2340
- name: "Anthropic Key",
2341
- regex: /sk-ant-api[a-zA-Z0-9-]{32,}/,
2342
- severity: "high",
2343
- description: "Anthropic API Key"
2344
- },
2345
- // Google
2346
- {
2347
- name: "Google API Key",
2348
- regex: /AIzaSy[0-9A-Za-z-_]{33}/,
2349
- severity: "high",
2350
- description: "Google API Key"
2351
- },
2352
- // Stripe
2353
- {
2354
- name: "Stripe Live Key",
2355
- regex: /sk_live_[0-9a-zA-Z]{24,}/,
2356
- severity: "high",
2357
- description: "Stripe Live Secret Key"
2358
- },
2359
- {
2360
- name: "Stripe Test Key",
2361
- regex: /sk_test_[0-9a-zA-Z]{24,}/,
2362
- severity: "low",
2363
- description: "Stripe Test Secret Key"
2364
- },
2365
- // Private Keys
2366
- {
2367
- name: "Private Key",
2368
- regex: /-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/,
2369
- severity: "high",
2370
- description: "Private Key File"
2371
- },
2372
- // Database URLs with credentials
2373
- {
2374
- name: "Database URL",
2375
- regex: /(postgres|postgresql|mysql|mongodb|redis):\/\/[^:]+:[^@]+@/,
2376
- severity: "high",
2377
- description: "Database URL with credentials"
2378
- },
2379
- // JWT Tokens
2380
- {
2381
- name: "JWT Token",
2382
- regex: /eyJ[a-zA-Z0-9]{10,}\.eyJ[a-zA-Z0-9]{10,}\.[a-zA-Z0-9_-]{10,}/,
2383
- severity: "medium",
2384
- description: "JSON Web Token"
2385
- },
2386
- // Generic patterns (lower priority)
2387
- {
2388
- name: "Generic API Key",
2389
- regex: /[aA][pP][iI][-_]?[kK][eE][yY]\s*[:=]\s*['"][a-zA-Z0-9]{16,}['"]/,
2390
- severity: "medium",
2391
- description: "Generic API Key Assignment"
2392
- },
2393
- {
2394
- name: "Generic Secret",
2395
- regex: /[sS][eE][cC][rR][eE][tT]\s*[:=]\s*['"][^'"]{8,}['"]/,
2396
- severity: "medium",
2397
- description: "Generic Secret Assignment"
2398
- },
2399
- {
2400
- name: "Password Assignment",
2401
- regex: /[pP][aA][sS][sS][wW][oO][rR][dD]\s*[:=]\s*['"][^'"]{4,}['"]/,
2402
- severity: "medium",
2403
- description: "Password Assignment"
2740
+ // src/core/metaTools/MetaToolService.ts
2741
+ var STOP_WORDS = /* @__PURE__ */ new Set([
2742
+ "a",
2743
+ "an",
2744
+ "and",
2745
+ "by",
2746
+ "for",
2747
+ "from",
2748
+ "in",
2749
+ "of",
2750
+ "on",
2751
+ "the",
2752
+ "to",
2753
+ "with",
2754
+ "find",
2755
+ "search",
2756
+ "list",
2757
+ "get",
2758
+ "show",
2759
+ "analyze",
2760
+ "count",
2761
+ "run",
2762
+ "quick",
2763
+ "tool",
2764
+ "tools",
2765
+ "file",
2766
+ "files",
2767
+ "codebase",
2768
+ "workspace",
2769
+ "source",
2770
+ "across"
2771
+ ]);
2772
+ function normalizeHandler(handler) {
2773
+ return handler.trim().replace(/\s+/g, " ");
2774
+ }
2775
+ function tokenize2(value) {
2776
+ const tokens = value.toLowerCase().split(/[^a-z0-9]+/).map((token) => token.endsWith("s") ? token.slice(0, -1) : token).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
2777
+ return new Set(tokens);
2778
+ }
2779
+ function overlapRatio(left, right) {
2780
+ if (left.size === 0 || right.size === 0) {
2781
+ return 0;
2782
+ }
2783
+ let intersection = 0;
2784
+ for (const token of left) {
2785
+ if (right.has(token)) {
2786
+ intersection++;
2787
+ }
2788
+ }
2789
+ return intersection / Math.min(left.size, right.size);
2790
+ }
2791
+ function isSimilarTool(candidate, existing) {
2792
+ const candidateNameTokens = tokenize2(candidate.name);
2793
+ const existingNameTokens = tokenize2(existing.name);
2794
+ if (overlapRatio(candidateNameTokens, existingNameTokens) >= 0.75) {
2795
+ return true;
2796
+ }
2797
+ const candidateDescriptionTokens = tokenize2(candidate.description);
2798
+ const existingDescriptionTokens = tokenize2(_nullishCoalesce(existing.description, () => ( "")));
2799
+ return overlapRatio(candidateDescriptionTokens, existingDescriptionTokens) >= 0.75;
2800
+ }
2801
+ var MetaToolService = class {
2802
+ constructor(registry) {
2803
+ this.registry = registry;
2804
+ }
2805
+
2806
+ async createMetaTool(input, registeredTools) {
2807
+ const parsed = MetaToolCreateInputSchema.safeParse(input);
2808
+ if (!parsed.success) {
2809
+ throw new Error(`Invalid meta-tool definition: ${_nullishCoalesce(_optionalChain([parsed, 'access', _36 => _36.error, 'access', _37 => _37.issues, 'access', _38 => _38[0], 'optionalAccess', _39 => _39.message]), () => ( "unknown validation error"))}`);
2810
+ }
2811
+ const definitionInput = parsed.data;
2812
+ assertSafeMetaToolHandler(definitionInput.handler);
2813
+ const fingerprint = fingerprintMetaTool(definitionInput);
2814
+ const existingByName = this.registry.getMetaTool(definitionInput.name);
2815
+ if (existingByName) {
2816
+ if (existingByName.fingerprint === fingerprint) {
2817
+ return {
2818
+ status: "existing",
2819
+ definition: existingByName,
2820
+ message: `Meta-tool "${definitionInput.name}" already exists with the same definition.`
2821
+ };
2404
2822
  }
2823
+ throw new Error(`Cannot create meta-tool "${definitionInput.name}": already exists with a different definition`);
2824
+ }
2825
+ const registeredNameConflict = registeredTools.find((tool) => tool.name === definitionInput.name);
2826
+ if (registeredNameConflict) {
2827
+ throw new Error(`Cannot create meta-tool "${definitionInput.name}": conflicts with existing tool`);
2828
+ }
2829
+ for (const existing of this.registry.getAllMetaTools()) {
2830
+ if (normalizeHandler(existing.handler) === normalizeHandler(definitionInput.handler)) {
2831
+ throw new Error(`Cannot create meta-tool "${definitionInput.name}": same handler already exists as "${existing.name}"`);
2832
+ }
2833
+ }
2834
+ const existingTools = [
2835
+ ...registeredTools,
2836
+ ...this.registry.getAllMetaTools().map((tool) => ({
2837
+ name: tool.name,
2838
+ description: tool.description
2839
+ }))
2405
2840
  ];
2406
- /**
2407
- * Placeholder patterns to ignore (false positives)
2408
- * These must be exact matches or specific patterns, not substrings
2409
- */
2410
- this.placeholderPatterns = [
2411
- /your[-_]?api[-_]?key/i,
2412
- /your[-_]?secret/i,
2413
- /\*\*\*/,
2414
- /\.\.\.$/,
2415
- /-example/i,
2416
- /placeholder/i,
2417
- /sk-xxx$/i,
2418
- /sk-your/i,
2419
- /<your[-_]?key[-_]?here>/i,
2420
- /\$\{[A-Z_]+\}/,
2421
- // Environment variable placeholders
2422
- /process\.env\./
2423
- ];
2841
+ const similar = existingTools.find((tool) => tool.name !== definitionInput.name && isSimilarTool(definitionInput, tool));
2842
+ if (similar) {
2843
+ throw new Error(`Cannot create meta-tool "${definitionInput.name}": similar existing tool "${similar.name}" should be reused`);
2844
+ }
2845
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2846
+ const saved = await this.registry.saveMetaTool({
2847
+ ...definitionInput,
2848
+ schemaVersion: 1,
2849
+ createdAt: now,
2850
+ updatedAt: now,
2851
+ fingerprint
2852
+ });
2853
+ return {
2854
+ status: "created",
2855
+ definition: saved,
2856
+ message: `Created meta-tool "${saved.name}" - available in this and future sessions`
2857
+ };
2424
2858
  }
2859
+ };
2860
+
2861
+ // src/core/SecurityScanner.ts
2862
+ var SecurityScanner = (_class2 = class {constructor() { _class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this); }
2863
+ /**
2864
+ * Built-in secret detection patterns
2865
+ */
2866
+ __init4() {this.patterns = [
2867
+ // AWS
2868
+ {
2869
+ name: "AWS Access Key",
2870
+ regex: /AKIA[0-9A-Z]{16}/,
2871
+ severity: "high",
2872
+ description: "AWS Access Key ID"
2873
+ },
2874
+ // GitHub
2875
+ {
2876
+ name: "GitHub Token",
2877
+ regex: /ghp_[a-zA-Z0-9]{36}/,
2878
+ severity: "high",
2879
+ description: "GitHub Personal Access Token"
2880
+ },
2881
+ {
2882
+ name: "GitHub OAuth",
2883
+ regex: /gho_[a-zA-Z0-9]{36}/,
2884
+ severity: "high",
2885
+ description: "GitHub OAuth Token"
2886
+ },
2887
+ {
2888
+ name: "GitHub App Token",
2889
+ regex: /ghu_[a-zA-Z0-9]{36}/,
2890
+ severity: "high",
2891
+ description: "GitHub App User Token"
2892
+ },
2893
+ // OpenAI / Anthropic
2894
+ {
2895
+ name: "OpenAI Key",
2896
+ regex: /sk-proj-[a-zA-Z0-9]{32,}/,
2897
+ severity: "high",
2898
+ description: "OpenAI Project API Key"
2899
+ },
2900
+ {
2901
+ name: "Anthropic Key",
2902
+ regex: /sk-ant-api[a-zA-Z0-9-]{32,}/,
2903
+ severity: "high",
2904
+ description: "Anthropic API Key"
2905
+ },
2906
+ // Google
2907
+ {
2908
+ name: "Google API Key",
2909
+ regex: /AIzaSy[0-9A-Za-z-_]{33}/,
2910
+ severity: "high",
2911
+ description: "Google API Key"
2912
+ },
2913
+ // Stripe
2914
+ {
2915
+ name: "Stripe Live Key",
2916
+ regex: /sk_live_[0-9a-zA-Z]{24,}/,
2917
+ severity: "high",
2918
+ description: "Stripe Live Secret Key"
2919
+ },
2920
+ {
2921
+ name: "Stripe Test Key",
2922
+ regex: /sk_test_[0-9a-zA-Z]{24,}/,
2923
+ severity: "low",
2924
+ description: "Stripe Test Secret Key"
2925
+ },
2926
+ // Private Keys
2927
+ {
2928
+ name: "Private Key",
2929
+ regex: /-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/,
2930
+ severity: "high",
2931
+ description: "Private Key File"
2932
+ },
2933
+ // Database URLs with credentials
2934
+ {
2935
+ name: "Database URL",
2936
+ regex: /(postgres|postgresql|mysql|mongodb|redis):\/\/[^:]+:[^@]+@/,
2937
+ severity: "high",
2938
+ description: "Database URL with credentials"
2939
+ },
2940
+ // JWT Tokens
2941
+ {
2942
+ name: "JWT Token",
2943
+ regex: /eyJ[a-zA-Z0-9]{10,}\.eyJ[a-zA-Z0-9]{10,}\.[a-zA-Z0-9_-]{10,}/,
2944
+ severity: "medium",
2945
+ description: "JSON Web Token"
2946
+ },
2947
+ // Generic patterns (lower priority)
2948
+ {
2949
+ name: "Generic API Key",
2950
+ regex: /[aA][pP][iI][-_]?[kK][eE][yY]\s*[:=]\s*['"][a-zA-Z0-9]{16,}['"]/,
2951
+ severity: "medium",
2952
+ description: "Generic API Key Assignment"
2953
+ },
2954
+ {
2955
+ name: "Generic Secret",
2956
+ regex: /[sS][eE][cC][rR][eE][tT]\s*[:=]\s*['"][^'"]{8,}['"]/,
2957
+ severity: "medium",
2958
+ description: "Generic Secret Assignment"
2959
+ },
2960
+ {
2961
+ name: "Password Assignment",
2962
+ regex: /[pP][aA][sS][sS][wW][oO][rR][dD]\s*[:=]\s*['"][^'"]{4,}['"]/,
2963
+ severity: "medium",
2964
+ description: "Password Assignment"
2965
+ }
2966
+ ]}
2967
+ /**
2968
+ * Placeholder patterns to ignore (false positives)
2969
+ * These must be exact matches or specific patterns, not substrings
2970
+ */
2971
+ __init5() {this.placeholderPatterns = [
2972
+ /your[-_]?api[-_]?key/i,
2973
+ /your[-_]?secret/i,
2974
+ /\*\*\*/,
2975
+ /\.\.\.$/,
2976
+ /-example/i,
2977
+ /placeholder/i,
2978
+ /sk-xxx$/i,
2979
+ /sk-your/i,
2980
+ /<your[-_]?key[-_]?here>/i,
2981
+ /\$\{[A-Z_]+\}/,
2982
+ // Environment variable placeholders
2983
+ /process\.env\./
2984
+ ]}
2425
2985
  /**
2426
2986
  * Scan git diff for secrets
2427
2987
  * @param diff - Git diff output
@@ -2581,7 +3141,9 @@ var SecurityScanner = class {
2581
3141
  lines.push("");
2582
3142
  }
2583
3143
  if (result.blockedCount > 0) {
2584
- lines.push(`[BLOCKED] ${result.blockedCount} high-severity secrets found`);
3144
+ lines.push(
3145
+ `[BLOCKED] ${result.blockedCount} high-severity secrets found`
3146
+ );
2585
3147
  lines.push(" Remove secrets before committing.");
2586
3148
  lines.push(" Consider using environment variables instead.");
2587
3149
  } else if (result.warningCount > 0) {
@@ -2600,7 +3162,7 @@ var SecurityScanner = class {
2600
3162
  const redacted = secret.slice(0, 4) + "*".repeat(secret.length - 8) + secret.slice(-4);
2601
3163
  return line.replace(secret, redacted);
2602
3164
  }
2603
- };
3165
+ }, _class2);
2604
3166
 
2605
3167
  // src/core/actionExecutor.ts
2606
3168
 
@@ -2609,8 +3171,9 @@ var SecurityScanner = class {
2609
3171
 
2610
3172
 
2611
3173
  var PlanFileStorage = class {
3174
+
2612
3175
  constructor() {
2613
- this.plansDir = _chunkSEKD5FH3cjs.AUTOHAND_PATHS.plans;
3176
+ this.plansDir = _chunkE26KKI46cjs.AUTOHAND_PATHS.plans;
2614
3177
  }
2615
3178
  /**
2616
3179
  * Get the plans directory path
@@ -2743,10 +3306,9 @@ var PlanFileStorage = class {
2743
3306
 
2744
3307
  // src/core/actionExecutor.ts
2745
3308
 
2746
- var ActionExecutor = class _ActionExecutor {
2747
- constructor(deps) {
3309
+ var ActionExecutor = (_class3 = class _ActionExecutor {
3310
+ constructor(deps) {;_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);
2748
3311
  this.deps = deps;
2749
- this.searchCache = /* @__PURE__ */ new Map();
2750
3312
  this.runtime = deps.runtime;
2751
3313
  this.files = deps.files;
2752
3314
  this.resolveWorkspacePath = deps.resolveWorkspacePath;
@@ -2754,17 +3316,91 @@ var ActionExecutor = class _ActionExecutor {
2754
3316
  this.projectManager = deps.projectManager;
2755
3317
  this.sessionId = deps.sessionId;
2756
3318
  this.logExploration = deps.onExploration;
2757
- this.toolsRegistry = _nullishCoalesce(deps.toolsRegistry, () => ( new ToolsRegistry()));
3319
+ this.toolsRegistry = _nullishCoalesce(deps.toolsRegistry, () => ( createToolsRegistry(deps.runtime.workspaceRoot)));
3320
+ this.metaToolService = _nullishCoalesce(deps.metaToolService, () => ( new MetaToolService(this.toolsRegistry)));
2758
3321
  this.getRegisteredTools = _nullishCoalesce(deps.getRegisteredTools, () => ( (() => [])));
2759
- this.permissionManager = _nullishCoalesce(deps.permissionManager, () => ( new (0, _chunkJ6QET7EFcjs.PermissionManager)(deps.runtime.config.permissions)));
3322
+ this.permissionManager = _nullishCoalesce(deps.permissionManager, () => ( new (0, _chunkDEQVRSV5cjs.PermissionManager)(deps.runtime.config.permissions)));
2760
3323
  this.memoryManager = deps.memoryManager;
2761
3324
  this.onToolOutput = deps.onToolOutput;
2762
3325
  this.onFileModified = deps.onFileModified;
2763
3326
  this.onAskFollowup = deps.onAskFollowup;
2764
3327
  this.onPlanCreated = deps.onPlanCreated;
2765
3328
  this.onPermissionRequest = deps.onPermissionRequest;
3329
+ this.onReviewHook = deps.onReviewHook;
3330
+ this.onModalPause = deps.onModalPause;
3331
+ this.onRequestDirectoryAccess = deps.onRequestDirectoryAccess;
3332
+ this.onLiveCommandStart = deps.onLiveCommandStart;
3333
+ this.onLiveCommandOutput = deps.onLiveCommandOutput;
3334
+ this.onLiveCommandRemove = deps.onLiveCommandRemove;
3335
+ this.onMetaToolCreated = deps.onMetaToolCreated;
2766
3336
  this.securityScanner = new SecurityScanner();
2767
3337
  }
3338
+
3339
+
3340
+
3341
+
3342
+
3343
+
3344
+
3345
+
3346
+
3347
+
3348
+
3349
+
3350
+
3351
+
3352
+
3353
+
3354
+
3355
+
3356
+
3357
+
3358
+
3359
+
3360
+
3361
+
3362
+
3363
+
3364
+ __init6() {this.searchCache = /* @__PURE__ */ new Map()}
3365
+ __init7() {this.fffSearchProviderPromise = null}
3366
+ __init8() {this.fffSearchWorkspaceRoot = null}
3367
+ __init9() {this.fffSearchIdleTimer = null}
3368
+ static __initStatic() {this.FFF_SEARCH_IDLE_TTL_MS = 6e4}
3369
+ async getFFFSearchProvider() {
3370
+ if (this.fffSearchIdleTimer) {
3371
+ clearTimeout(this.fffSearchIdleTimer);
3372
+ this.fffSearchIdleTimer = null;
3373
+ }
3374
+ const workspaceRoot = this.runtime.workspaceRoot;
3375
+ if (this.fffSearchProviderPromise && this.fffSearchWorkspaceRoot === workspaceRoot) {
3376
+ return this.fffSearchProviderPromise;
3377
+ }
3378
+ if (this.fffSearchProviderPromise) {
3379
+ this.fffSearchProviderPromise.then((provider) => provider.destroy()).catch(() => {
3380
+ });
3381
+ }
3382
+ const { FFFSearchProvider } = await Promise.resolve().then(() => _interopRequireWildcard(require("./fffSearchProvider-W6627E2V.cjs")));
3383
+ this.fffSearchWorkspaceRoot = workspaceRoot;
3384
+ this.fffSearchProviderPromise = FFFSearchProvider.create(workspaceRoot);
3385
+ return this.fffSearchProviderPromise;
3386
+ }
3387
+ scheduleFFFSearchProviderCleanup() {
3388
+ if (!this.fffSearchProviderPromise) {
3389
+ return;
3390
+ }
3391
+ if (this.fffSearchIdleTimer) {
3392
+ clearTimeout(this.fffSearchIdleTimer);
3393
+ }
3394
+ this.fffSearchIdleTimer = setTimeout(() => {
3395
+ const providerPromise = this.fffSearchProviderPromise;
3396
+ this.fffSearchProviderPromise = null;
3397
+ this.fffSearchWorkspaceRoot = null;
3398
+ this.fffSearchIdleTimer = null;
3399
+ _optionalChain([providerPromise, 'optionalAccess', _40 => _40.then, 'call', _41 => _41((provider) => provider.destroy()), 'access', _42 => _42.catch, 'call', _43 => _43(() => {
3400
+ })]);
3401
+ }, _ActionExecutor.FFF_SEARCH_IDLE_TTL_MS);
3402
+ _optionalChain([this, 'access', _44 => _44.fffSearchIdleTimer, 'access', _45 => _45.unref, 'optionalCall', _46 => _46()]);
3403
+ }
2768
3404
  /**
2769
3405
  * Check permission hooks before prompting user.
2770
3406
  * Returns true if allowed, false if denied/blocked, undefined if should ask user.
@@ -2774,7 +3410,7 @@ var ActionExecutor = class _ActionExecutor {
2774
3410
  return {};
2775
3411
  }
2776
3412
  const hookResponse = await this.onPermissionRequest(context);
2777
- if (!_optionalChain([hookResponse, 'optionalAccess', _43 => _43.decision])) {
3413
+ if (!_optionalChain([hookResponse, 'optionalAccess', _47 => _47.decision])) {
2778
3414
  return {};
2779
3415
  }
2780
3416
  switch (hookResponse.decision) {
@@ -2790,7 +3426,7 @@ var ActionExecutor = class _ActionExecutor {
2790
3426
  }
2791
3427
  }
2792
3428
  async execute(action, context) {
2793
- if (this.runtime.options.dryRun && action.type !== "search" && action.type !== "plan") {
3429
+ if (this.runtime.options.dryRun && !["fff_grep", "fff_find", "find", "search", "search_with_context", "semantic_search", "glob", "plan"].includes(action.type)) {
2794
3430
  return "Dry-run mode: skipped mutation";
2795
3431
  }
2796
3432
  switch (action.type) {
@@ -2815,7 +3451,7 @@ var ActionExecutor = class _ActionExecutor {
2815
3451
  console.log(_chalk2.default.gray(`
2816
3452
  \u{1F9F9} Cleaned up ${cleanedCount} plan(s) older than 30 days`));
2817
3453
  }
2818
- const planModeManager = _chunkULQ6MDSJcjs.getPlanModeManager.call(void 0, );
3454
+ const planModeManager = _chunkLFDPTJYFcjs.getPlanModeManager.call(void 0, );
2819
3455
  if (planModeManager.isEnabled() && this.onAskFollowup) {
2820
3456
  const refreshedPlanIds = await storage.listPlans();
2821
3457
  const incompletePlans = [];
@@ -2985,11 +3621,15 @@ ${steps.map((s) => `${s.number}. ${s.description}`).join("\n")}`;
2985
3621
  const receivedKeys = Object.keys(action).filter((k) => k !== "type").join(", ") || "none";
2986
3622
  throw new Error(`write_file requires a "path" argument. Received arguments: [${receivedKeys}]`);
2987
3623
  }
3624
+ if (action.contents === void 0 && action.content === void 0) {
3625
+ return 'Error: write_file requires "contents" argument.';
3626
+ }
2988
3627
  const filePath = this.resolveWorkspacePath(action.path);
2989
3628
  const fs7 = await Promise.resolve().then(() => _interopRequireWildcard(require("fs-extra")));
2990
3629
  const exists = this.files.root && await fs7.pathExists(filePath);
2991
3630
  const oldContent = exists ? await this.files.readFile(action.path) : "";
2992
3631
  const newContent = _nullishCoalesce(this.pickText(action.contents, action.content), () => ( ""));
3632
+ let resultOutput = null;
2993
3633
  if (!exists) {
2994
3634
  const permContext = {
2995
3635
  tool: "write_file",
@@ -3035,16 +3675,18 @@ ${steps.map((s) => `${s.number}. ${s.description}`).join("\n")}`;
3035
3675
  }
3036
3676
  }
3037
3677
  }
3678
+ resultOutput = this.formatDiffPreview("", newContent, action.path);
3038
3679
  } else if (oldContent === newContent) {
3039
3680
  return `No changes needed for ${action.path} (content identical)`;
3040
3681
  } else {
3041
3682
  console.log(_chalk2.default.cyan(`
3042
3683
  \u{1F4DD} ${action.path}:`));
3043
3684
  this.showDiff(oldContent, newContent, action.path);
3685
+ resultOutput = this.formatDiffPreview(oldContent, newContent, action.path);
3044
3686
  }
3045
3687
  await this.files.writeFile(action.path, newContent);
3046
- _optionalChain([this, 'access', _44 => _44.onFileModified, 'optionalCall', _45 => _45(action.path)]);
3047
- return exists ? `Updated ${action.path}` : `Created ${action.path}`;
3688
+ _optionalChain([this, 'access', _48 => _48.onFileModified, 'optionalCall', _49 => _49(action.path, exists ? "modify" : "create")]);
3689
+ return _nullishCoalesce(resultOutput, () => ( (exists ? `Updated ${action.path}` : `Created ${action.path}`)));
3048
3690
  }
3049
3691
  case "append_file": {
3050
3692
  if (!action.path) {
@@ -3057,17 +3699,17 @@ ${steps.map((s) => `${s.number}. ${s.description}`).join("\n")}`;
3057
3699
  \u{1F4DD} ${action.path}:`));
3058
3700
  this.showDiff(oldContent, newContent, action.path);
3059
3701
  await this.files.appendFile(action.path, addition);
3060
- _optionalChain([this, 'access', _46 => _46.onFileModified, 'optionalCall', _47 => _47(action.path)]);
3061
- return `Appended to ${action.path}`;
3702
+ _optionalChain([this, 'access', _50 => _50.onFileModified, 'optionalCall', _51 => _51(action.path, "modify")]);
3703
+ return this.formatDiffPreview(oldContent, newContent, action.path);
3062
3704
  }
3063
3705
  case "apply_patch": {
3064
3706
  if (!action.path) {
3065
- throw new Error('apply_patch requires a "path" argument.');
3707
+ return 'Error: apply_patch requires a "path" argument.';
3066
3708
  }
3067
3709
  const oldContent = await this.files.readFile(action.path).catch(() => "");
3068
3710
  const patch = this.pickText(action.patch, action.diff);
3069
3711
  if (!patch) {
3070
- throw new Error("apply_patch requires patch or diff content.");
3712
+ return 'Error: apply_patch requires a "patch" argument.';
3071
3713
  }
3072
3714
  console.log(_chalk2.default.cyan(`
3073
3715
  \u{1F527} ${action.path}:`));
@@ -3075,58 +3717,60 @@ ${steps.map((s) => `${s.number}. ${s.description}`).join("\n")}`;
3075
3717
  await this.files.applyPatch(action.path, patch);
3076
3718
  const newContent = await this.files.readFile(action.path);
3077
3719
  this.showDiff(oldContent, newContent, action.path);
3078
- _optionalChain([this, 'access', _48 => _48.onFileModified, 'optionalCall', _49 => _49(action.path)]);
3079
- return `Patched ${action.path}`;
3720
+ _optionalChain([this, 'access', _52 => _52.onFileModified, 'optionalCall', _53 => _53(action.path, "modify")]);
3721
+ return this.formatDiffPreview(oldContent, newContent, action.path);
3722
+ }
3723
+ case "notebook_edit": {
3724
+ if (!action.path) {
3725
+ throw new Error('notebook_edit requires a "path" argument.');
3726
+ }
3727
+ const current = await this.files.readFile(action.path);
3728
+ const { updated, summary } = applyNotebookEdit(current, action);
3729
+ await this.files.writeFile(action.path, updated);
3730
+ _optionalChain([this, 'access', _54 => _54.onFileModified, 'optionalCall', _55 => _55(action.path, "modify")]);
3731
+ return summary;
3080
3732
  }
3081
3733
  case "tools_registry": {
3082
3734
  const tools = await this.toolsRegistry.listTools(this.getRegisteredTools());
3083
3735
  return JSON.stringify(tools, null, 2);
3084
3736
  }
3085
- case "search": {
3086
- const cacheKey = `search:${action.query}:${action.path || ""}`;
3087
- if (this.searchCache.has(cacheKey)) {
3088
- return `[Cached] ${this.searchCache.get(cacheKey)}`;
3089
- }
3090
- const hits = this.files.search(action.query, action.path);
3091
- this.recordExploration("search", action.query);
3092
- const result = hits.slice(0, 10).map((hit) => `${hit.file}:${hit.line}: ${hit.text}`).join("\n");
3093
- this.searchCache.set(cacheKey, result);
3094
- return result;
3095
- }
3096
- case "search_with_context": {
3097
- const cacheKey = `search_ctx:${action.query}:${action.path || ""}:${action.limit || ""}:${action.context || ""}`;
3098
- if (this.searchCache.has(cacheKey)) {
3099
- return `[Cached] ${this.searchCache.get(cacheKey)}`;
3100
- }
3101
- this.recordExploration("search", action.query);
3102
- const result = this.files.searchWithContext(action.query, {
3103
- limit: action.limit,
3104
- context: action.context,
3105
- relativePath: action.path
3106
- });
3107
- this.searchCache.set(cacheKey, result);
3108
- return result;
3109
- }
3110
- case "semantic_search": {
3111
- const cacheKey = `semantic:${action.query}:${action.path || ""}:${action.limit || ""}:${action.window || ""}`;
3112
- if (this.searchCache.has(cacheKey)) {
3113
- return `[Cached] ${this.searchCache.get(cacheKey)}`;
3737
+ case "tool_search": {
3738
+ const query = _optionalChain([action, 'access', _56 => _56.query, 'optionalAccess', _57 => _57.trim, 'call', _58 => _58()]);
3739
+ if (!query) {
3740
+ throw new Error('tool_search requires a non-empty "query" argument.');
3114
3741
  }
3115
- const results = this.files.semanticSearch(action.query, {
3116
- limit: action.limit,
3117
- window: action.window,
3118
- relativePath: action.path
3119
- });
3120
- if (!results.length) {
3121
- this.searchCache.set(cacheKey, "No matches found.");
3122
- return "No matches found.";
3123
- }
3124
- const result = results.map((hit) => `${_chalk2.default.cyan(hit.file)}
3125
- ${hit.snippet}`).join("\n\n");
3126
- this.searchCache.set(cacheKey, result);
3127
- return result;
3742
+ const limit = Math.max(1, _nullishCoalesce(action.limit, () => ( 10)));
3743
+ const tools = await this.toolsRegistry.listTools(this.getRegisteredTools());
3744
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
3745
+ const scored = tools.map((tool) => {
3746
+ const haystack = `${tool.name} ${tool.description}`.toLowerCase();
3747
+ let score = 0;
3748
+ for (const term of terms) {
3749
+ if (tool.name.toLowerCase() === term) {
3750
+ score += 10;
3751
+ } else if (tool.name.toLowerCase().includes(term)) {
3752
+ score += 6;
3753
+ }
3754
+ if (haystack.includes(term)) {
3755
+ score += 2;
3756
+ }
3757
+ }
3758
+ return { tool, score };
3759
+ }).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name)).slice(0, limit).map((entry) => entry.tool);
3760
+ return JSON.stringify(scored, null, 2);
3128
3761
  }
3762
+ case "find":
3763
+ return this.executeFind(action);
3764
+ case "glob":
3765
+ return this.executeGlob(action);
3766
+ case "fff_grep":
3767
+ return this.executeFFFGrep(action);
3768
+ case "fff_find":
3769
+ return this.executeFFFFind(action);
3129
3770
  case "create_directory": {
3771
+ if (!action.path) {
3772
+ return 'Error: create_directory requires a "path" argument.';
3773
+ }
3130
3774
  await this.files.createDirectory(action.path);
3131
3775
  return `Created directory ${action.path}`;
3132
3776
  }
@@ -3141,14 +3785,24 @@ ${hit.snippet}`).join("\n\n");
3141
3785
  if (!confirmed) {
3142
3786
  return `Skipped deleting ${action.path}`;
3143
3787
  }
3788
+ const oldDeleteContent = await this.files.readFile(action.path).catch(() => null);
3144
3789
  await this.files.deletePath(action.path);
3145
- return `Deleted ${action.path}`;
3790
+ if (oldDeleteContent !== null) {
3791
+ console.log(_chalk2.default.cyan(`
3792
+ \u{1F5D1}\uFE0F ${action.path}:`));
3793
+ this.showDiff(oldDeleteContent, "", action.path);
3794
+ _optionalChain([this, 'access', _59 => _59.onFileModified, 'optionalCall', _60 => _60(action.path, "delete")]);
3795
+ return this.formatDiffPreview(oldDeleteContent, "", action.path);
3796
+ }
3797
+ _optionalChain([this, 'access', _61 => _61.onFileModified, 'optionalCall', _62 => _62(action.path, "delete")]);
3798
+ return `Deleted directory ${action.path}`;
3146
3799
  }
3147
3800
  case "rename_path": {
3148
3801
  if (!action.from || !action.to) {
3149
3802
  throw new Error('rename_path requires "from" and "to" arguments.');
3150
3803
  }
3151
3804
  await this.files.renamePath(action.from, action.to);
3805
+ _optionalChain([this, 'access', _63 => _63.onFileModified, 'optionalCall', _64 => _64(action.to, "create")]);
3152
3806
  return `Renamed ${action.from} -> ${action.to}`;
3153
3807
  }
3154
3808
  case "copy_path": {
@@ -3156,9 +3810,16 @@ ${hit.snippet}`).join("\n\n");
3156
3810
  throw new Error('copy_path requires "from" and "to" arguments.');
3157
3811
  }
3158
3812
  await this.files.copyPath(action.from, action.to);
3813
+ _optionalChain([this, 'access', _65 => _65.onFileModified, 'optionalCall', _66 => _66(action.to, "create")]);
3159
3814
  return `Copied ${action.from} -> ${action.to}`;
3160
3815
  }
3161
3816
  case "search_replace": {
3817
+ if (!action.path) {
3818
+ return 'Error: search_replace requires a "path" argument.';
3819
+ }
3820
+ if (!action.blocks) {
3821
+ return 'Error: search_replace requires a "blocks" argument.';
3822
+ }
3162
3823
  const content = await this.files.readFile(action.path);
3163
3824
  const result = this.applySearchReplaceBlocks(content, action.blocks);
3164
3825
  if (content !== result) {
@@ -3166,47 +3827,102 @@ ${hit.snippet}`).join("\n\n");
3166
3827
  \u{1F504} ${action.path}:`));
3167
3828
  this.showDiff(content, result, action.path);
3168
3829
  await this.files.writeFile(action.path, result);
3169
- _optionalChain([this, 'access', _50 => _50.onFileModified, 'optionalCall', _51 => _51(action.path)]);
3830
+ _optionalChain([this, 'access', _67 => _67.onFileModified, 'optionalCall', _68 => _68(action.path, "modify")]);
3831
+ return this.formatDiffPreview(content, result, action.path);
3170
3832
  }
3171
- return `Updated ${action.path}`;
3833
+ return `No changes needed for ${action.path} (content identical)`;
3172
3834
  }
3173
3835
  case "format_file": {
3174
3836
  if (!action.path) {
3175
3837
  throw new Error('format_file requires a "path" argument.');
3176
3838
  }
3839
+ const oldFormatContent = await this.files.readFile(action.path).catch(() => "");
3177
3840
  await this.files.formatFile(action.path, (contents, file) => _chunk4JNNTOGFcjs.applyFormatter.call(void 0, action.formatter, contents, file));
3178
- return `Formatted ${action.path} (${action.formatter})`;
3841
+ const newFormatContent = await this.files.readFile(action.path).catch(() => "");
3842
+ if (oldFormatContent !== newFormatContent) {
3843
+ console.log(_chalk2.default.cyan(`
3844
+ \u{1F3A8} ${action.path}:`));
3845
+ this.showDiff(oldFormatContent, newFormatContent, action.path);
3846
+ _optionalChain([this, 'access', _69 => _69.onFileModified, 'optionalCall', _70 => _70(action.path, "modify")]);
3847
+ return this.formatDiffPreview(oldFormatContent, newFormatContent, action.path);
3848
+ }
3849
+ return `No changes needed (already formatted): ${action.path}`;
3179
3850
  }
3180
3851
  case "run_command": {
3181
3852
  if (!action.command || typeof action.command !== "string") {
3182
3853
  return 'Error: run_command requires a "command" argument (string)';
3183
3854
  }
3184
3855
  const shouldStreamOutput = Boolean(
3185
- this.onToolOutput && _optionalChain([context, 'optionalAccess', _52 => _52.toolCallId]) && !action.background && process.env.AUTOHAND_STREAM_TOOL_OUTPUT === "1"
3856
+ this.onToolOutput && _optionalChain([context, 'optionalAccess', _71 => _71.toolCallId]) && !action.background && process.env.AUTOHAND_STREAM_TOOL_OUTPUT === "1"
3186
3857
  );
3187
3858
  const emitOutput = (stream, data) => {
3188
3859
  if (!shouldStreamOutput) {
3189
3860
  return;
3190
3861
  }
3191
- _optionalChain([this, 'access', _53 => _53.onToolOutput, 'optionalCall', _54 => _54({
3862
+ _optionalChain([this, 'access', _72 => _72.onToolOutput, 'optionalCall', _73 => _73({
3192
3863
  tool: action.type,
3193
- toolCallId: _optionalChain([context, 'optionalAccess', _55 => _55.toolCallId]),
3864
+ toolCallId: _optionalChain([context, 'optionalAccess', _74 => _74.toolCallId]),
3194
3865
  stream,
3195
3866
  data
3196
3867
  })]);
3197
3868
  };
3198
- const result = await runCommand(
3199
- action.command,
3200
- _nullishCoalesce(action.args, () => ( [])),
3201
- this.runtime.workspaceRoot,
3202
- {
3203
- directory: action.directory,
3204
- background: action.background,
3205
- onStdout: (chunk) => emitOutput("stdout", chunk),
3206
- onStderr: (chunk) => emitOutput("stderr", chunk)
3207
- }
3208
- );
3209
3869
  const cmdStr = `${action.command} ${(_nullishCoalesce(action.args, () => ( []))).join(" ")}`.trim();
3870
+ if (action.interactive) {
3871
+ const onModalPause = this.onModalPause;
3872
+ if (onModalPause) {
3873
+ return await onModalPause(async () => {
3874
+ let result2;
3875
+ try {
3876
+ result2 = await _chunkWTB7AFL6cjs.runCommand.call(void 0,
3877
+ cmdStr,
3878
+ [],
3879
+ this.runtime.workspaceRoot,
3880
+ {
3881
+ directory: action.directory,
3882
+ shell: true,
3883
+ interactive: true
3884
+ }
3885
+ );
3886
+ } catch (err) {
3887
+ const error = err;
3888
+ if (error.code === "ENOENT" || error.message.includes("Command not found")) {
3889
+ return `Error: Command not found: "${action.command}". Make sure it is installed and available on your PATH.`;
3890
+ }
3891
+ return `Error running "${cmdStr}": ${error.message}`;
3892
+ }
3893
+ const header2 = action.description ? `$ ${action.description}
3894
+ > ${cmdStr}` : `$ ${cmdStr}`;
3895
+ const dirInfo2 = action.directory ? `[dir: ${action.directory}]` : "";
3896
+ const parts2 = [dirInfo2 ? `${header2} ${dirInfo2}` : header2];
3897
+ if (result2.code !== 0) {
3898
+ parts2.push(`(exit code: ${result2.code})`);
3899
+ }
3900
+ return parts2.join("\n");
3901
+ });
3902
+ }
3903
+ }
3904
+ let result;
3905
+ const shellCmd = cmdStr;
3906
+ try {
3907
+ result = await _chunkWTB7AFL6cjs.runCommand.call(void 0,
3908
+ shellCmd,
3909
+ [],
3910
+ this.runtime.workspaceRoot,
3911
+ {
3912
+ directory: action.directory,
3913
+ background: action.background,
3914
+ shell: true,
3915
+ onStdout: (chunk) => emitOutput("stdout", chunk),
3916
+ onStderr: (chunk) => emitOutput("stderr", chunk)
3917
+ }
3918
+ );
3919
+ } catch (err) {
3920
+ const error = err;
3921
+ if (error.code === "ENOENT" || error.message.includes("Command not found")) {
3922
+ return `Error: Command not found: "${action.command}". Make sure it is installed and available on your PATH.`;
3923
+ }
3924
+ return `Error running "${cmdStr}": ${error.message}`;
3925
+ }
3210
3926
  const header = action.description ? `$ ${action.description}
3211
3927
  > ${cmdStr}` : `$ ${cmdStr}`;
3212
3928
  const dirInfo = action.directory ? `[dir: ${action.directory}]` : "";
@@ -3220,12 +3936,100 @@ ${hit.snippet}`).join("\n\n");
3220
3936
  }
3221
3937
  return parts.join("\n");
3222
3938
  }
3939
+ case "shell": {
3940
+ if (!action.command || typeof action.command !== "string") {
3941
+ return 'Error: shell requires a "command" argument (string)';
3942
+ }
3943
+ const cmdStr = `${action.command} ${(_nullishCoalesce(action.args, () => ( []))).join(" ")}`.trim();
3944
+ const commandId = _optionalChain([this, 'access', _75 => _75.onLiveCommandStart, 'optionalCall', _76 => _76(cmdStr)]);
3945
+ const hasLiveDisplay = Boolean(commandId);
3946
+ if (hasLiveDisplay) {
3947
+ const liveId = commandId;
3948
+ try {
3949
+ const result2 = await _chunkWBU4Q4GScjs.executeStreamingShellCommand.call(void 0,
3950
+ cmdStr,
3951
+ this.runtime.workspaceRoot,
3952
+ {
3953
+ onStdout: (chunk) => this.onLiveCommandOutput(liveId, "stdout", chunk),
3954
+ onStderr: (chunk) => this.onLiveCommandOutput(liveId, "stderr", chunk),
3955
+ preferPty: process.stdin.isTTY && process.stdout.isTTY,
3956
+ columns: process.stdout.columns,
3957
+ rows: process.stdout.rows,
3958
+ background: action.background
3959
+ }
3960
+ );
3961
+ this.onLiveCommandRemove(liveId);
3962
+ const header2 = action.description ? `$ ${action.description}
3963
+ > ${cmdStr}` : `$ ${cmdStr}`;
3964
+ const dirInfo2 = action.directory ? `[dir: ${action.directory}]` : "";
3965
+ const parts2 = [dirInfo2 ? `${header2} ${dirInfo2}` : header2];
3966
+ if (result2.output) parts2.push(result2.output);
3967
+ if (result2.error) parts2.push(result2.error);
3968
+ if (result2.backgroundPid) parts2.push(`[Background PID: ${result2.backgroundPid}]`);
3969
+ return parts2.join("\n");
3970
+ } catch (err) {
3971
+ this.onLiveCommandRemove(liveId);
3972
+ const error = err;
3973
+ return `Error running "${cmdStr}": ${error.message}`;
3974
+ }
3975
+ }
3976
+ let result;
3977
+ try {
3978
+ result = await _chunkWTB7AFL6cjs.runCommand.call(void 0,
3979
+ cmdStr,
3980
+ [],
3981
+ this.runtime.workspaceRoot,
3982
+ {
3983
+ directory: action.directory,
3984
+ shell: true,
3985
+ background: action.background
3986
+ }
3987
+ );
3988
+ } catch (err) {
3989
+ const error = err;
3990
+ if (error.code === "ENOENT" || error.message.includes("Command not found")) {
3991
+ return `Error: Command not found: "${action.command}". Make sure it is installed and available on your PATH.`;
3992
+ }
3993
+ return `Error running "${cmdStr}": ${error.message}`;
3994
+ }
3995
+ const header = action.description ? `$ ${action.description}
3996
+ > ${cmdStr}` : `$ ${cmdStr}`;
3997
+ const dirInfo = action.directory ? `[dir: ${action.directory}]` : "";
3998
+ const parts = [
3999
+ dirInfo ? `${header} ${dirInfo}` : header,
4000
+ result.stdout,
4001
+ result.stderr
4002
+ ].filter(Boolean);
4003
+ return parts.join("\n");
4004
+ }
3223
4005
  case "add_dependency": {
4006
+ const fseAdd = (await Promise.resolve().then(() => _interopRequireWildcard(require("fs-extra")))).default;
4007
+ const pkgPathAdd = `${this.runtime.workspaceRoot}/package.json`;
4008
+ const oldPkgAdd = await fseAdd.readFile(pkgPathAdd, "utf-8").catch(() => "");
3224
4009
  await addDependency(this.runtime.workspaceRoot, action.name, action.version, { dev: action.dev });
4010
+ const newPkgAdd = await fseAdd.readFile(pkgPathAdd, "utf-8").catch(() => "");
4011
+ if (oldPkgAdd !== newPkgAdd) {
4012
+ console.log(_chalk2.default.cyan(`
4013
+ \u{1F4E6} package.json:`));
4014
+ this.showDiff(oldPkgAdd, newPkgAdd, "package.json");
4015
+ _optionalChain([this, 'access', _77 => _77.onFileModified, 'optionalCall', _78 => _78("package.json", "modify")]);
4016
+ return this.formatDiffPreview(oldPkgAdd, newPkgAdd, "package.json");
4017
+ }
3225
4018
  return `Added dependency ${action.name}@${action.version}${action.dev ? " (dev)" : ""}`;
3226
4019
  }
3227
4020
  case "remove_dependency": {
4021
+ const fseRm = (await Promise.resolve().then(() => _interopRequireWildcard(require("fs-extra")))).default;
4022
+ const pkgPathRm = `${this.runtime.workspaceRoot}/package.json`;
4023
+ const oldPkgRm = await fseRm.readFile(pkgPathRm, "utf-8").catch(() => "");
3228
4024
  await removeDependency(this.runtime.workspaceRoot, action.name, { dev: action.dev });
4025
+ const newPkgRm = await fseRm.readFile(pkgPathRm, "utf-8").catch(() => "");
4026
+ if (oldPkgRm !== newPkgRm) {
4027
+ console.log(_chalk2.default.cyan(`
4028
+ \u{1F4E6} package.json:`));
4029
+ this.showDiff(oldPkgRm, newPkgRm, "package.json");
4030
+ _optionalChain([this, 'access', _79 => _79.onFileModified, 'optionalCall', _80 => _80("package.json", "modify")]);
4031
+ return this.formatDiffPreview(oldPkgRm, newPkgRm, "package.json");
4032
+ }
3229
4033
  return `Removed dependency ${action.name}${action.dev ? " (dev)" : ""}`;
3230
4034
  }
3231
4035
  case "list_tree": {
@@ -3254,11 +4058,7 @@ ${hit.snippet}`).join("\n\n");
3254
4058
  return `${_nullishCoalesce(action.algorithm, () => ( "sha256"))} ${action.path}: ${sum}`;
3255
4059
  }
3256
4060
  case "git_diff": {
3257
- if (!action.path) {
3258
- throw new Error('git_diff requires a "path" argument.');
3259
- }
3260
- this.resolveWorkspacePath(action.path);
3261
- const rawDiff = diffFile(this.runtime.workspaceRoot, action.path);
4061
+ const rawDiff = action.path ? (this.resolveWorkspacePath(action.path), diffFile(this.runtime.workspaceRoot, action.path)) : diffWorkspace(this.runtime.workspaceRoot);
3262
4062
  return this.colorizeGitDiff(rawDiff);
3263
4063
  }
3264
4064
  case "git_checkout": {
@@ -3266,8 +4066,17 @@ ${hit.snippet}`).join("\n\n");
3266
4066
  throw new Error('git_checkout requires a "path" argument.');
3267
4067
  }
3268
4068
  this.resolveWorkspacePath(action.path);
4069
+ const oldCheckoutContent = await this.files.readFile(action.path).catch(() => "");
3269
4070
  checkoutFile(this.runtime.workspaceRoot, action.path);
3270
- return `Restored ${action.path} from git.`;
4071
+ const newCheckoutContent = await this.files.readFile(action.path).catch(() => "");
4072
+ if (oldCheckoutContent !== newCheckoutContent) {
4073
+ console.log(_chalk2.default.cyan(`
4074
+ \u21A9\uFE0F ${action.path}:`));
4075
+ this.showDiff(oldCheckoutContent, newCheckoutContent, action.path);
4076
+ _optionalChain([this, 'access', _81 => _81.onFileModified, 'optionalCall', _82 => _82(action.path, "modify")]);
4077
+ return this.formatDiffPreview(oldCheckoutContent, newCheckoutContent, action.path);
4078
+ }
4079
+ return `Restored ${action.path} from git (no changes).`;
3271
4080
  }
3272
4081
  case "git_status":
3273
4082
  return gitStatus(this.runtime.workspaceRoot);
@@ -3537,8 +4346,10 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3537
4346
  console.log(_chalk2.default.cyan("Suggested commit message:"));
3538
4347
  console.log(_chalk2.default.white(` ${commitMessage}`));
3539
4348
  console.log();
4349
+ const normalizedYolo = _chunkJ5HE6CUMcjs.normalizeYoloInput.call(void 0, this.runtime.options.yolo);
4350
+ const yoloAllowsCommit = normalizedYolo && _chunkJ5HE6CUMcjs.isToolAllowedByYolo.call(void 0, "auto_commit", _chunkJ5HE6CUMcjs.parseYoloPattern.call(void 0, normalizedYolo));
3540
4351
  const autoApproveCommit = Boolean(
3541
- this.runtime.options.yes || process.env.CI === "1" || process.env.AUTOHAND_NON_INTERACTIVE === "1"
4352
+ this.runtime.options.unrestricted || this.runtime.options.yes || yoloAllowsCommit || process.env.CI === "1" || process.env.AUTOHAND_NON_INTERACTIVE === "1"
3542
4353
  );
3543
4354
  if (autoApproveCommit) {
3544
4355
  console.log(_chalk2.default.gray("Auto-commit approval enabled; committing without prompt."));
@@ -3553,26 +4364,36 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3553
4364
  return result2.message;
3554
4365
  }
3555
4366
  const options = [
3556
- { label: "Yes - commit with this message", value: "y" },
4367
+ { label: `Yes - commit with this message`, value: "y" },
3557
4368
  { label: "Edit - modify the message", value: "e" },
3558
4369
  { label: "No - cancel commit", value: "n" }
3559
4370
  ];
3560
- const modalResult = await _chunkZYQMLKOKcjs.showModal.call(void 0, {
3561
- title: "Commit with this message?",
3562
- options
3563
- });
3564
- if (!modalResult || modalResult.value === "n") {
4371
+ const runModal = async () => {
4372
+ const modalResult = await _chunkCH2J4PVEcjs.showModal.call(void 0, {
4373
+ title: `Commit with this message?
4374
+
4375
+ "${commitMessage}"`,
4376
+ options
4377
+ });
4378
+ if (!modalResult || modalResult.value === "n") {
4379
+ return { cancelled: true, editedMessage: null };
4380
+ }
4381
+ if (modalResult.value === "e") {
4382
+ const editedMessage = await _chunkCH2J4PVEcjs.showInput.call(void 0, {
4383
+ title: "Enter commit message:",
4384
+ defaultValue: commitMessage
4385
+ });
4386
+ return { cancelled: false, editedMessage };
4387
+ }
4388
+ return { cancelled: false, editedMessage: null };
4389
+ };
4390
+ const modalOutcome = this.onModalPause ? await this.onModalPause(runModal) : await runModal();
4391
+ if (modalOutcome.cancelled) {
3565
4392
  console.log(_chalk2.default.yellow("Commit cancelled."));
3566
4393
  return "Commit cancelled by user";
3567
4394
  }
3568
- if (modalResult.value === "e") {
3569
- const editedMessage = await _chunkZYQMLKOKcjs.showInput.call(void 0, {
3570
- title: "Enter commit message:",
3571
- defaultValue: commitMessage
3572
- });
3573
- if (editedMessage) {
3574
- commitMessage = editedMessage;
3575
- }
4395
+ if (modalOutcome.editedMessage) {
4396
+ commitMessage = modalOutcome.editedMessage;
3576
4397
  }
3577
4398
  const result = executeAutoCommit(this.runtime.workspaceRoot, commitMessage, action.stage_all !== false);
3578
4399
  if (result.success) {
@@ -3606,6 +4427,12 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3606
4427
  case "custom_command":
3607
4428
  return this.executeCustomCommand(action);
3608
4429
  case "multi_file_edit": {
4430
+ if (!action.file_path) {
4431
+ return 'Error: multi_file_edit requires a "file_path" argument.';
4432
+ }
4433
+ if (!action.edits || !Array.isArray(action.edits)) {
4434
+ return 'Error: multi_file_edit requires an "edits" argument (array).';
4435
+ }
3609
4436
  const oldContent = await this.files.readFile(action.file_path);
3610
4437
  let newContent = oldContent;
3611
4438
  console.log(_chalk2.default.cyan(`
@@ -3646,14 +4473,20 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3646
4473
  }
3647
4474
  }
3648
4475
  if (firstIndex === -1) {
3649
- console.log(_chalk2.default.red(` \u2717 Edit ${i + 1}: Could not find text to replace`));
3650
- console.log(_chalk2.default.gray(` Looking for (${edit.old_string.length} chars):`));
3651
- console.log(_chalk2.default.gray(` "${edit.old_string.substring(0, 80)}${edit.old_string.length > 80 ? "..." : ""}"`));
3652
4476
  const similar = this.findSimilarText(newContent, edit.old_string);
3653
4477
  if (similar) {
3654
- console.log(_chalk2.default.yellow(` Did you mean:`));
3655
- console.log(_chalk2.default.yellow(` "${similar.substring(0, 80)}${similar.length > 80 ? "..." : ""}"`));
4478
+ const similarIndex = newContent.indexOf(similar);
4479
+ if (similarIndex !== -1) {
4480
+ newContent = newContent.substring(0, similarIndex) + edit.new_string + newContent.substring(similarIndex + similar.length);
4481
+ console.log(_chalk2.default.yellow(` \u26A0 Edit ${i + 1}: Applied with fuzzy match (whitespace/indentation differed)`));
4482
+ console.log(_chalk2.default.gray(` Original search: "${edit.old_string.substring(0, 60)}${edit.old_string.length > 60 ? "..." : ""}"`));
4483
+ console.log(_chalk2.default.gray(` Matched: "${similar.substring(0, 60)}${similar.length > 60 ? "..." : ""}"`));
4484
+ continue;
4485
+ }
3656
4486
  }
4487
+ console.log(_chalk2.default.red(` \u2717 Edit ${i + 1}: Could not find text to replace`));
4488
+ console.log(_chalk2.default.gray(` Looking for (${edit.old_string.length} chars):`));
4489
+ console.log(_chalk2.default.gray(` "${edit.old_string.substring(0, 80)}${edit.old_string.length > 80 ? "..." : ""}"`));
3657
4490
  if (edit.old_string.length < 100) {
3658
4491
  const nonAscii = edit.old_string.match(/[^\x20-\x7E\n\r\t]/g);
3659
4492
  if (nonAscii && nonAscii.length > 0) {
@@ -3669,9 +4502,10 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3669
4502
  if (oldContent !== newContent) {
3670
4503
  this.showDiff(oldContent, newContent, action.file_path);
3671
4504
  await this.files.writeFile(action.file_path, newContent);
3672
- _optionalChain([this, 'access', _56 => _56.onFileModified, 'optionalCall', _57 => _57(action.file_path)]);
4505
+ _optionalChain([this, 'access', _83 => _83.onFileModified, 'optionalCall', _84 => _84(action.file_path, "modify")]);
4506
+ return this.formatDiffPreview(oldContent, newContent, action.file_path);
3673
4507
  }
3674
- return `Applied ${action.edits.length} edit(s) to ${action.file_path}`;
4508
+ return `No changes needed for ${action.file_path} (content identical)`;
3675
4509
  }
3676
4510
  case "todo_write": {
3677
4511
  const todoPath = ".autohand/agents/tasks/todos.json";
@@ -3681,17 +4515,17 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3681
4515
  }
3682
4516
  const validTasks = action.tasks.filter((task) => {
3683
4517
  if (!task) return false;
3684
- const hasId = !!task.id;
3685
4518
  const hasContent = !!(task.content || task.title);
3686
- return hasId && hasContent;
4519
+ return hasContent;
3687
4520
  });
3688
- const normalizedTasks = validTasks.map((task) => {
4521
+ const normalizedTasks = validTasks.map((task, index) => {
3689
4522
  const content = task.content || task.title || "";
3690
4523
  const title = content;
3691
4524
  return {
3692
4525
  ...task,
3693
4526
  // Preserve extra properties like priority, tags, etc.
3694
- id: task.id,
4527
+ id: task.id || `task-${Date.now()}-${index}`,
4528
+ // Auto-generate id if missing
3695
4529
  title,
3696
4530
  content,
3697
4531
  // Keep original content field
@@ -3702,24 +4536,51 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3702
4536
  });
3703
4537
  const allTodos = normalizedTasks;
3704
4538
  await this.files.writeFile(todoPath, JSON.stringify(allTodos, null, 2));
3705
- console.log(_chalk2.default.cyan("\n\u{1F4CB} Task Progress:"));
4539
+ _optionalChain([this, 'access', _85 => _85.onFileModified, 'optionalCall', _86 => _86(todoPath, "modify")]);
3706
4540
  const total = allTodos.length;
3707
- const completed = allTodos.filter((t) => t.status === "completed").length;
4541
+ if (total === 0) {
4542
+ console.log(_chalk2.default.dim("\n\u{1F4CB} Task list cleared"));
4543
+ console.log();
4544
+ return "Task list cleared (0 tasks)";
4545
+ }
4546
+ const completedTasks = allTodos.filter((t) => t.status === "completed");
3708
4547
  const inProgress = allTodos.filter((t) => t.status === "in_progress");
3709
- const pending = allTodos.filter((t) => t.status === "pending").length;
3710
- const percent = total > 0 ? Math.round(completed / total * 100) : 0;
4548
+ const pendingTasks = allTodos.filter((t) => t.status === "pending");
4549
+ const completed = completedTasks.length;
4550
+ const pending = pendingTasks.length;
4551
+ const percent = Math.round(completed / total * 100);
3711
4552
  const barWidth = 20;
3712
4553
  const filled = Math.round(barWidth * percent / 100);
3713
4554
  const bar = "\u2588".repeat(filled) + "\u2591".repeat(barWidth - filled);
3714
- console.log(` ${_chalk2.default.green(bar)} ${percent}%`);
3715
- console.log(_chalk2.default.gray(` ${completed} done \xB7 ${inProgress.length} in progress \xB7 ${pending} pending`));
4555
+ const titleOf = (task) => {
4556
+ const title = _nullishCoalesce(task.title, () => ( task.content));
4557
+ return typeof title === "string" && title.trim().length > 0 ? title : "Untitled task";
4558
+ };
4559
+ const outputLines = [
4560
+ _chalk2.default.cyan("\n\u{1F4CB} Task Progress:"),
4561
+ ` ${_chalk2.default.green(bar)} ${percent}%`,
4562
+ _chalk2.default.gray(` ${completed} done \xB7 ${inProgress.length} in progress \xB7 ${pending} pending`)
4563
+ ];
4564
+ if (completedTasks.length > 0) {
4565
+ outputLines.push("", _chalk2.default.green(" \u2705 Completed Tasks:"));
4566
+ for (const task of completedTasks) {
4567
+ outputLines.push(_chalk2.default.green(` \u2713 ${titleOf(task)}`));
4568
+ }
4569
+ }
3716
4570
  if (inProgress.length > 0) {
3717
- console.log(_chalk2.default.yellow("\n \u{1F504} Active Tasks:"));
4571
+ outputLines.push("", _chalk2.default.yellow(" \u{1F504} Active Tasks:"));
3718
4572
  for (const task of inProgress) {
3719
- console.log(` \u2022 ${task.title || task.content}`);
4573
+ outputLines.push(_chalk2.default.yellow(` \u2022 ${titleOf(task)}`));
3720
4574
  }
3721
4575
  }
3722
- console.log();
4576
+ if (pendingTasks.length > 0) {
4577
+ outputLines.push("", _chalk2.default.cyan(" \u23F3 Pending Tasks:"));
4578
+ for (const task of pendingTasks) {
4579
+ outputLines.push(_chalk2.default.dim(` \u25CB ${titleOf(task)}`));
4580
+ }
4581
+ }
4582
+ console.log(`${outputLines.join("\n")}
4583
+ `);
3723
4584
  return `Updated task list: ${percent}% complete (${completed}/${total})`;
3724
4585
  }
3725
4586
  case "save_memory": {
@@ -3747,58 +4608,21 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3747
4608
  return formatted;
3748
4609
  }
3749
4610
  case "create_meta_tool": {
3750
- if (!action.name || !action.description || !action.handler) {
3751
- throw new Error("create_meta_tool requires name, description, and handler");
3752
- }
3753
- const builtInNames = this.getRegisteredTools().map((t) => t.name);
3754
- if (builtInNames.includes(action.name)) {
3755
- throw new Error(`Cannot create meta-tool "${action.name}": conflicts with built-in tool`);
3756
- }
3757
- const dangerousPatterns = [
3758
- // Destructive file operations
3759
- { pattern: /rm\s+(-[rf]+\s+)*\/(?!\w)/i, description: "rm with root path" },
3760
- { pattern: /rm\s+.*--no-preserve-root/i, description: "rm --no-preserve-root" },
3761
- { pattern: /dd\s+.*(?:of|if)=\/dev\/[sh]d/i, description: "dd to disk device" },
3762
- { pattern: /mkfs\./i, description: "filesystem format" },
3763
- { pattern: /wipefs/i, description: "disk wipe" },
3764
- // Privilege escalation
3765
- { pattern: /\bsudo\s/i, description: "sudo command" },
3766
- { pattern: /\bsu\s+-?\s*\w/i, description: "su command" },
3767
- { pattern: /chmod\s+[0-7]*7[0-7]*/i, description: "world-writable chmod" },
3768
- { pattern: /chown\s+root/i, description: "chown to root" },
3769
- // Remote code execution
3770
- { pattern: /curl\s+.*\|\s*(ba)?sh/i, description: "curl | bash" },
3771
- { pattern: /wget\s+.*\|\s*(ba)?sh/i, description: "wget | sh" },
3772
- { pattern: /\beval\s+[`$]/i, description: "eval with expansion" },
3773
- // Fork bomb and resource exhaustion
3774
- { pattern: /:\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;/i, description: "fork bomb" },
3775
- { pattern: /while\s+true.*do.*done/i, description: "infinite loop" },
3776
- // Reverse shell indicators
3777
- { pattern: /nc\s+.*-e\s*\/bin/i, description: "netcat reverse shell" },
3778
- { pattern: /ncat\s+.*-e\s*\/bin/i, description: "ncat reverse shell" },
3779
- { pattern: /bash\s+-i\s+>&?\s*\/dev\/tcp/i, description: "bash reverse shell" },
3780
- // Dangerous network operations
3781
- { pattern: /iptables\s+-F/i, description: "flush firewall rules" },
3782
- // Crypto operations that could lock out user
3783
- { pattern: /gpg\s+.*--encrypt.*-r\s+\S+\s+\//i, description: "gpg encrypt root" }
3784
- ];
3785
- for (const { pattern, description } of dangerousPatterns) {
3786
- if (pattern.test(action.handler)) {
3787
- throw new Error(`Handler contains dangerous pattern: ${description}`);
3788
- }
3789
- }
3790
- await this.toolsRegistry.saveMetaTool({
4611
+ const result = await this.metaToolService.createMetaTool({
3791
4612
  name: action.name,
3792
4613
  description: action.description,
3793
4614
  parameters: _nullishCoalesce(action.parameters, () => ( { type: "object", properties: {} })),
3794
4615
  handler: action.handler,
3795
- source: "agent"
3796
- });
4616
+ source: "agent",
4617
+ scope: _nullishCoalesce(action.scope, () => ( "user"))
4618
+ }, this.getRegisteredTools());
4619
+ const metaTool = result.definition;
4620
+ _optionalChain([this, 'access', _87 => _87.onMetaToolCreated, 'optionalCall', _88 => _88(metaTool)]);
3797
4621
  console.log(_chalk2.default.green(`
3798
- \u{1F527} Created meta-tool: ${action.name}`));
4622
+ \u{1F527} ${result.status === "created" ? "Created" : "Reused"} meta-tool: ${metaTool.name}`));
3799
4623
  console.log(_chalk2.default.gray(` ${action.description}`));
3800
4624
  console.log(_chalk2.default.gray(` Handler: ${action.handler}`));
3801
- return `Created meta-tool "${action.name}" - available in this and future sessions`;
4625
+ return result.message;
3802
4626
  }
3803
4627
  // Web Search Operations
3804
4628
  case "web_search": {
@@ -3807,11 +4631,11 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3807
4631
  }
3808
4632
  console.log(_chalk2.default.cyan(`
3809
4633
  \u{1F50D} Searching web: "${action.query}"...`));
3810
- const results = await _chunkRKJTGGMUcjs.webSearch.call(void 0, action.query, {
4634
+ const results = await _chunkWKRDBCP2cjs.webSearch.call(void 0, action.query, {
3811
4635
  maxResults: action.max_results,
3812
4636
  searchType: action.search_type
3813
4637
  });
3814
- const formatted = _chunkRKJTGGMUcjs.formatSearchResults.call(void 0, results);
4638
+ const formatted = _chunkWKRDBCP2cjs.formatSearchResults.call(void 0, results);
3815
4639
  console.log(_chalk2.default.gray(formatted.split("\n").slice(0, 10).join("\n")));
3816
4640
  if (results.length > 3) {
3817
4641
  console.log(_chalk2.default.gray(" ..."));
@@ -3824,7 +4648,7 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3824
4648
  }
3825
4649
  console.log(_chalk2.default.cyan(`
3826
4650
  \u{1F310} Fetching: ${action.url}...`));
3827
- const content = await _chunkRKJTGGMUcjs.fetchUrl.call(void 0, action.url, {
4651
+ const content = await _chunkWKRDBCP2cjs.fetchUrl.call(void 0, action.url, {
3828
4652
  maxLength: action.max_length
3829
4653
  });
3830
4654
  const preview = content.slice(0, 500);
@@ -3838,11 +4662,11 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3838
4662
  const registryLabel = action.registry ? ` (${action.registry})` : "";
3839
4663
  console.log(_chalk2.default.cyan(`
3840
4664
  \u{1F4E6} Getting package info: ${action.package_name}${action.version ? `@${action.version}` : ""}${registryLabel}...`));
3841
- const info = await _chunkRKJTGGMUcjs.getPackageInfo.call(void 0, action.package_name, {
4665
+ const info = await _chunkWKRDBCP2cjs.getPackageInfo.call(void 0, action.package_name, {
3842
4666
  registry: action.registry,
3843
4667
  version: action.version
3844
4668
  });
3845
- const formatted = _chunkRKJTGGMUcjs.formatPackageInfo.call(void 0, info);
4669
+ const formatted = _chunkWKRDBCP2cjs.formatPackageInfo.call(void 0, info);
3846
4670
  console.log(_chalk2.default.gray(formatted));
3847
4671
  return formatted;
3848
4672
  }
@@ -3877,12 +4701,24 @@ ${result.removed.map((p) => ` - ${p}`).join("\n")}`;
3877
4701
  console.log(_chalk2.default.gray(previewResult + (formattedResult.length > 500 ? "\n ... (truncated)" : "")));
3878
4702
  return formattedResult;
3879
4703
  }
4704
+ // Project Tracker
4705
+ case "project_tracker": {
4706
+ if (!action.action) {
4707
+ throw new Error('project_tracker requires an "action" parameter.');
4708
+ }
4709
+ console.log(_chalk2.default.cyan(`
4710
+ \u{1F50D} project_tracker: ${action.action}${action.number ? ` #${action.number}` : ""}...`));
4711
+ const trackerResult = await projectTracker(action);
4712
+ const trackerPreview = trackerResult.slice(0, 500);
4713
+ console.log(_chalk2.default.gray(trackerPreview + (trackerResult.length > 500 ? "\n ... (truncated)" : "")));
4714
+ return trackerResult;
4715
+ }
3880
4716
  // Skills Discovery
3881
4717
  case "find_agent_skills": {
3882
4718
  const query = _nullishCoalesce(action.query, () => ( ""));
3883
4719
  console.log(_chalk2.default.cyan(`
3884
4720
  Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...`));
3885
- const { searchCommunitySkills } = await Promise.resolve().then(() => _interopRequireWildcard(require("./skills-FYY6F2WV.cjs")));
4721
+ const { searchCommunitySkills } = await Promise.resolve().then(() => _interopRequireWildcard(require("./skills-GGMZOVIE.cjs")));
3886
4722
  const result = await searchCommunitySkills(query, {
3887
4723
  category: action.category,
3888
4724
  limit: action.limit
@@ -3908,17 +4744,17 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
3908
4744
  label: `${options.length + 1}. Other (type your own answer)`,
3909
4745
  value: "__other__"
3910
4746
  });
3911
- const result = await _chunkZYQMLKOKcjs.showModal.call(void 0, {
4747
+ const result = await _chunkCH2J4PVEcjs.showModal.call(void 0, {
3912
4748
  title: "Select an answer:",
3913
4749
  options
3914
4750
  });
3915
- const selected = _optionalChain([result, 'optionalAccess', _58 => _58.value]);
4751
+ const selected = _optionalChain([result, 'optionalAccess', _89 => _89.value]);
3916
4752
  if (!selected) {
3917
4753
  console.log(_chalk2.default.yellow("\nAnswer cancelled.\n"));
3918
4754
  return "<answer>No answer provided</answer>";
3919
4755
  }
3920
4756
  if (selected === "__other__") {
3921
- const answer = await _chunkZYQMLKOKcjs.showInput.call(void 0, {
4757
+ const answer = await _chunkCH2J4PVEcjs.showInput.call(void 0, {
3922
4758
  title: "Your answer:"
3923
4759
  });
3924
4760
  if (!answer) {
@@ -3935,7 +4771,7 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
3935
4771
  `));
3936
4772
  return `<answer>${selected}</answer>`;
3937
4773
  } else {
3938
- const answer = await _chunkZYQMLKOKcjs.showInput.call(void 0, {
4774
+ const answer = await _chunkCH2J4PVEcjs.showInput.call(void 0, {
3939
4775
  title: "Your answer:"
3940
4776
  });
3941
4777
  const finalAnswer = answer || "No answer provided";
@@ -3945,6 +4781,32 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
3945
4781
  return `<answer>${finalAnswer}</answer>`;
3946
4782
  }
3947
4783
  }
4784
+ // Code review tool
4785
+ // Directory access tool
4786
+ case "request_directory_access": {
4787
+ return this.executeRequestDirectoryAccess(action);
4788
+ }
4789
+ case "code_review": {
4790
+ return this.executeCodeReview(action);
4791
+ }
4792
+ // Browser tools — forwarded to Chrome extension via RPC
4793
+ case "browser_screenshot":
4794
+ case "browser_click":
4795
+ case "browser_type":
4796
+ case "browser_navigate":
4797
+ case "browser_scroll":
4798
+ case "browser_find_element":
4799
+ case "browser_press_key":
4800
+ case "browser_get_page_context":
4801
+ case "browser_get_element":
4802
+ case "browser_wait_for_element":
4803
+ case "browser_read_network":
4804
+ case "browser_read_console":
4805
+ case "browser_get_tabs":
4806
+ case "browser_get_tab_groups":
4807
+ case "browser_execute_js": {
4808
+ return this.executeBrowserTool(action);
4809
+ }
3948
4810
  default: {
3949
4811
  const actionType = action.type;
3950
4812
  const metaTool = this.toolsRegistry.getMetaTool(actionType);
@@ -3955,6 +4817,145 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
3955
4817
  }
3956
4818
  }
3957
4819
  }
4820
+ async executeBrowserTool(action) {
4821
+ const { type, ...params } = action;
4822
+ const toolName = type;
4823
+ const { invokeBrowserTool } = await Promise.resolve().then(() => _interopRequireWildcard(require("./browserToolBridge-BXRQB4B4.cjs")));
4824
+ return invokeBrowserTool(toolName, params);
4825
+ }
4826
+ async executeRequestDirectoryAccess(action) {
4827
+ const path8 = await Promise.resolve().then(() => _interopRequireWildcard(require("path")));
4828
+ const fs7 = (await Promise.resolve().then(() => _interopRequireWildcard(require("fs-extra")))).default;
4829
+ const { checkWorkspaceSafety } = await Promise.resolve().then(() => _interopRequireWildcard(require("./workspaceSafety-MDJGHK6D.cjs")));
4830
+ const resolvedPath = path8.resolve(action.path);
4831
+ if (!await fs7.pathExists(resolvedPath)) {
4832
+ return `Error: Directory does not exist: ${resolvedPath}`;
4833
+ }
4834
+ const stats = await fs7.stat(resolvedPath);
4835
+ if (!stats.isDirectory()) {
4836
+ return `Error: Path is not a directory: ${resolvedPath}`;
4837
+ }
4838
+ const safetyResult = checkWorkspaceSafety(resolvedPath);
4839
+ if (!safetyResult.safe) {
4840
+ return `Error: Unsafe directory: ${resolvedPath}. ${safetyResult.reason}`;
4841
+ }
4842
+ const workspaceRoot = this.runtime.workspaceRoot;
4843
+ const additionalDirs = this.files.getAllowedDirectories();
4844
+ if (resolvedPath === workspaceRoot || additionalDirs.includes(resolvedPath)) {
4845
+ return `Directory is already accessible: ${resolvedPath}`;
4846
+ }
4847
+ const normalizedResolved = resolvedPath.endsWith(path8.sep) ? resolvedPath.slice(0, -1) : resolvedPath;
4848
+ const normalizedWorkspace = workspaceRoot.endsWith(path8.sep) ? workspaceRoot.slice(0, -1) : workspaceRoot;
4849
+ if (normalizedResolved.startsWith(normalizedWorkspace + path8.sep)) {
4850
+ return `Directory is already within workspace: ${resolvedPath}`;
4851
+ }
4852
+ for (const dir of additionalDirs) {
4853
+ const normalizedDir = dir.endsWith(path8.sep) ? dir.slice(0, -1) : dir;
4854
+ if (normalizedResolved.startsWith(normalizedDir + path8.sep) || normalizedResolved === normalizedDir) {
4855
+ return `Directory is already accessible: ${resolvedPath}`;
4856
+ }
4857
+ }
4858
+ if (this.onRequestDirectoryAccess) {
4859
+ const result = await this.onRequestDirectoryAccess(resolvedPath, action.reason);
4860
+ if (result) {
4861
+ this.files.addAdditionalDirectory(resolvedPath);
4862
+ return `Access granted to directory: ${resolvedPath}
4863
+
4864
+ You can now use file tools (read_file, write_file, glob, find, etc.) to work with files in this directory.`;
4865
+ } else {
4866
+ return `Access denied to directory: ${resolvedPath}`;
4867
+ }
4868
+ }
4869
+ const normalizedYolo = _chunkJ5HE6CUMcjs.normalizeYoloInput.call(void 0, this.runtime.options.yolo);
4870
+ if (normalizedYolo) {
4871
+ this.files.addAdditionalDirectory(resolvedPath);
4872
+ return `Access auto-granted (yolo mode) to directory: ${resolvedPath}
4873
+
4874
+ You can now use file tools (read_file, write_file, glob, find, etc.) to work with files in this directory.`;
4875
+ }
4876
+ if (this.runtime.options.unrestricted || this.runtime.options.yes) {
4877
+ this.files.addAdditionalDirectory(resolvedPath);
4878
+ return `Access auto-granted to directory: ${resolvedPath}
4879
+
4880
+ You can now use file tools (read_file, write_file, glob, find, etc.) to work with files in this directory.`;
4881
+ }
4882
+ return `Directory access required: ${resolvedPath}
4883
+
4884
+ To grant access, use:
4885
+ /add-dir ${resolvedPath}
4886
+
4887
+ Or restart with:
4888
+ --add-dir ${resolvedPath}`;
4889
+ }
4890
+ async executeCodeReview(action) {
4891
+ const targetPath = action.path ? this.resolveWorkspacePath(action.path) : this.runtime.workspaceRoot;
4892
+ const scope = action.scope || "full";
4893
+ await _optionalChain([this, 'access', _90 => _90.onReviewHook, 'optionalCall', _91 => _91("review:start", {
4894
+ reviewPath: targetPath,
4895
+ reviewScope: scope,
4896
+ reviewInstructions: action.instructions
4897
+ })]);
4898
+ try {
4899
+ let context = "";
4900
+ if (scope === "diff") {
4901
+ const { execFile: execFile2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("child_process")));
4902
+ const { promisify } = await Promise.resolve().then(() => _interopRequireWildcard(require("util")));
4903
+ const execFileAsync = promisify(execFile2);
4904
+ const result2 = await execFileAsync("git", ["diff", "--stat"], {
4905
+ cwd: this.runtime.workspaceRoot,
4906
+ encoding: "utf8"
4907
+ }).catch(() => null);
4908
+ context = _optionalChain([result2, 'optionalAccess', _92 => _92.stdout]) || "No uncommitted changes found.";
4909
+ } else if (scope === "file" && action.path) {
4910
+ const fse = (await Promise.resolve().then(() => _interopRequireWildcard(require("fs-extra")))).default;
4911
+ context = await fse.readFile(targetPath, "utf-8").catch(() => `Could not read ${targetPath}`);
4912
+ } else {
4913
+ const { execFile: execFile2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("child_process")));
4914
+ const { promisify } = await Promise.resolve().then(() => _interopRequireWildcard(require("util")));
4915
+ const execFileAsync = promisify(execFile2);
4916
+ const tree = await execFileAsync("find", [
4917
+ targetPath,
4918
+ "-maxdepth",
4919
+ "3",
4920
+ "-type",
4921
+ "f",
4922
+ "-not",
4923
+ "-path",
4924
+ "*/node_modules/*",
4925
+ "-not",
4926
+ "-path",
4927
+ "*/.git/*"
4928
+ ], {
4929
+ cwd: this.runtime.workspaceRoot,
4930
+ encoding: "utf8"
4931
+ }).catch(() => null);
4932
+ context = _optionalChain([tree, 'optionalAccess', _93 => _93.stdout]) || "";
4933
+ }
4934
+ const result = [
4935
+ `Code review initiated for: ${targetPath}`,
4936
+ `Scope: ${scope}`,
4937
+ action.instructions ? `Focus: ${action.instructions}` : "",
4938
+ "",
4939
+ "Project structure:",
4940
+ context.slice(0, 5e3)
4941
+ ].filter(Boolean).join("\n");
4942
+ await _optionalChain([this, 'access', _94 => _94.onReviewHook, 'optionalCall', _95 => _95("review:completed", {
4943
+ reviewPath: targetPath,
4944
+ reviewScope: scope,
4945
+ reviewInstructions: action.instructions
4946
+ })]);
4947
+ return result;
4948
+ } catch (error) {
4949
+ const message = error instanceof Error ? error.message : String(error);
4950
+ await _optionalChain([this, 'access', _96 => _96.onReviewHook, 'optionalCall', _97 => _97("review:failed", {
4951
+ reviewPath: targetPath,
4952
+ reviewScope: scope,
4953
+ reviewInstructions: action.instructions,
4954
+ reviewError: message
4955
+ })]);
4956
+ return `Review failed: ${message}`;
4957
+ }
4958
+ }
3958
4959
  pickText(...values) {
3959
4960
  for (const value of values) {
3960
4961
  if (typeof value === "string") {
@@ -3968,7 +4969,7 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
3968
4969
  * Identifies imports, classes, functions, and key sections with line numbers.
3969
4970
  */
3970
4971
  extractFileOutline(lines, filePath) {
3971
- const ext = _optionalChain([filePath, 'access', _59 => _59.split, 'call', _60 => _60("."), 'access', _61 => _61.pop, 'call', _62 => _62(), 'optionalAccess', _63 => _63.toLowerCase, 'call', _64 => _64()]) || "";
4972
+ const ext = _optionalChain([filePath, 'access', _98 => _98.split, 'call', _99 => _99("."), 'access', _100 => _100.pop, 'call', _101 => _101(), 'optionalAccess', _102 => _102.toLowerCase, 'call', _103 => _103()]) || "";
3972
4973
  const outline = [];
3973
4974
  const patterns = {
3974
4975
  ts: [
@@ -4051,11 +5052,127 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4051
5052
  }
4052
5053
  return result.length > 0 ? result.join("\n") : "No structure detected";
4053
5054
  }
5055
+ executeFind(action) {
5056
+ console.warn(_chalk2.default.yellow("[DEPRECATED] The `find` tool is deprecated. Use `fff_grep` instead. Will be removed in v0.9.0."));
5057
+ const mode = _nullishCoalesce(action.mode, () => ( (action.context && action.context > 0 ? "context" : "exact")));
5058
+ const cacheKey = `find:${mode}:${action.query}:${action.path || ""}:${action.limit || ""}:${action.context || ""}:${action.window || ""}`;
5059
+ if (this.searchCache.has(cacheKey)) {
5060
+ return `[Cached] ${this.searchCache.get(cacheKey)}`;
5061
+ }
5062
+ this.recordExploration("search", action.query);
5063
+ if (mode === "semantic") {
5064
+ const results = this.files.semanticSearch(action.query, {
5065
+ limit: action.limit,
5066
+ window: action.window,
5067
+ relativePath: action.path
5068
+ });
5069
+ if (!results.length) {
5070
+ this.searchCache.set(cacheKey, "No matches found.");
5071
+ return "No matches found.";
5072
+ }
5073
+ const result2 = results.map((hit) => `${_chalk2.default.cyan(hit.file)}
5074
+ ${hit.snippet}`).join("\n\n");
5075
+ this.searchCache.set(cacheKey, result2);
5076
+ return result2;
5077
+ }
5078
+ if (mode === "context") {
5079
+ const result2 = this.files.searchWithContext(action.query, {
5080
+ limit: action.limit,
5081
+ context: action.context,
5082
+ relativePath: action.path
5083
+ });
5084
+ this.searchCache.set(cacheKey, result2);
5085
+ return result2;
5086
+ }
5087
+ const hits = this.files.search(action.query, action.path);
5088
+ const result = hits.slice(0, _nullishCoalesce(action.limit, () => ( 10))).map((hit) => `${hit.file}:${hit.line}: ${hit.text}`).join("\n");
5089
+ this.searchCache.set(cacheKey, result);
5090
+ return result;
5091
+ }
5092
+ async executeGlob(action) {
5093
+ console.warn(_chalk2.default.yellow("[DEPRECATED] The `glob` tool is deprecated. Use `fff_find` instead. Will be removed in v0.9.0."));
5094
+ const { resolveRipgrepCommand } = await Promise.resolve().then(() => _interopRequireWildcard(require("./ripgrep-67SCU2BA.cjs")));
5095
+ const rgPath = resolveRipgrepCommand();
5096
+ const searchPath = action.path ? this.resolveWorkspacePath(action.path) : this.runtime.workspaceRoot;
5097
+ const limit = _nullishCoalesce(action.limit, () => ( 100));
5098
+ const args = ["--files"];
5099
+ const patterns = _nullishCoalesce(action.patterns, () => ( (action.pattern ? [action.pattern] : ["**/*"])));
5100
+ for (const p of patterns) {
5101
+ args.push("--glob", p);
5102
+ }
5103
+ args.push(searchPath);
5104
+ const { execFile: execFile2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("child_process")));
5105
+ const { promisify } = await Promise.resolve().then(() => _interopRequireWildcard(require("util")));
5106
+ const execFileAsync = promisify(execFile2);
5107
+ try {
5108
+ const result = await execFileAsync(rgPath, args, {
5109
+ cwd: this.runtime.workspaceRoot,
5110
+ encoding: "utf8",
5111
+ maxBuffer: 10 * 1024 * 1024
5112
+ });
5113
+ const files = result.stdout.trim().split("\n").filter(Boolean);
5114
+ if (files.length === 0) {
5115
+ return "No files found matching the pattern.";
5116
+ }
5117
+ const fse = (await Promise.resolve().then(() => _interopRequireWildcard(require("fs-extra")))).default;
5118
+ const withStats = await Promise.all(
5119
+ files.map(async (f) => {
5120
+ try {
5121
+ const stat = await fse.stat(f);
5122
+ return { file: f, mtime: stat.mtimeMs };
5123
+ } catch (e8) {
5124
+ return { file: f, mtime: 0 };
5125
+ }
5126
+ })
5127
+ );
5128
+ withStats.sort((a, b) => b.mtime - a.mtime);
5129
+ const sorted = withStats.map((s) => s.file);
5130
+ const limited = sorted.slice(0, limit);
5131
+ const header = `Found ${files.length} file${files.length === 1 ? "" : "s"}${files.length > limit ? ` (showing first ${limit})` : ""}`;
5132
+ this.recordExploration("list", _nullishCoalesce(_nullishCoalesce(action.pattern, () => ( _optionalChain([action, 'access', _104 => _104.patterns, 'optionalAccess', _105 => _105.join, 'call', _106 => _106(", ")]))), () => ( "*")));
5133
+ return `${header}
5134
+ ${limited.join("\n")}`;
5135
+ } catch (error) {
5136
+ const exitCode = _optionalChain([error, 'optionalAccess', _107 => _107.code]);
5137
+ if (exitCode === 1 || exitCode === "1") {
5138
+ return "No files found matching the pattern.";
5139
+ }
5140
+ throw error;
5141
+ }
5142
+ }
5143
+ async executeFFFGrep(action) {
5144
+ const provider = await this.getFFFSearchProvider();
5145
+ try {
5146
+ return await provider.grep({
5147
+ query: action.query,
5148
+ path: action.path,
5149
+ exclude: action.exclude,
5150
+ caseSensitive: action.caseSensitive,
5151
+ beforeContext: action.beforeContext,
5152
+ afterContext: action.afterContext,
5153
+ classifyDefinitions: action.classifyDefinitions,
5154
+ limit: action.limit
5155
+ });
5156
+ } finally {
5157
+ this.scheduleFFFSearchProviderCleanup();
5158
+ }
5159
+ }
5160
+ async executeFFFFind(action) {
5161
+ const provider = await this.getFFFSearchProvider();
5162
+ try {
5163
+ return await provider.fileSearch({
5164
+ query: action.query,
5165
+ limit: action.limit
5166
+ });
5167
+ } finally {
5168
+ this.scheduleFFFSearchProviderCleanup();
5169
+ }
5170
+ }
4054
5171
  recordExploration(kind, target) {
4055
5172
  if (!target) {
4056
5173
  return;
4057
5174
  }
4058
- _optionalChain([this, 'access', _65 => _65.logExploration, 'optionalCall', _66 => _66({ kind, target })]);
5175
+ _optionalChain([this, 'access', _108 => _108.logExploration, 'optionalCall', _109 => _109({ kind, target })]);
4059
5176
  }
4060
5177
  async executeCustomCommand(action) {
4061
5178
  const existing = await loadCustomCommand(action.name);
@@ -4085,19 +5202,13 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4085
5202
  }
4086
5203
  await saveCustomCommand(definition);
4087
5204
  }
4088
- const result = await runCommand(definition.command, _nullishCoalesce(definition.args, () => ( [])), this.runtime.workspaceRoot);
5205
+ const result = await _chunkWTB7AFL6cjs.runCommand.call(void 0, definition.command, _nullishCoalesce(definition.args, () => ( [])), this.runtime.workspaceRoot);
4089
5206
  return [`$ ${definition.command} ${(_nullishCoalesce(definition.args, () => ( []))).join(" ")}`, result.stdout, result.stderr].filter(Boolean).join("\n");
4090
5207
  }
4091
5208
  isDestructiveCommand(command) {
4092
5209
  const lowered = command.toLowerCase();
4093
5210
  return lowered.includes("rm ") || lowered.includes("sudo ") || lowered.includes("dd ");
4094
5211
  }
4095
- static {
4096
- /**
4097
- * Shell metacharacters that could enable command injection
4098
- */
4099
- this.SHELL_METACHARACTERS = /[|;&$`><(){}[\]!#*?~'"\\]/;
4100
- }
4101
5212
  /**
4102
5213
  * Safely escape a value for shell interpolation
4103
5214
  * Uses single quotes which prevent all shell expansion except for single quotes themselves
@@ -4118,21 +5229,62 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4118
5229
  if (value === void 0 || value === null) {
4119
5230
  throw new Error(`Missing required parameter "${paramName}" for meta-tool "${metaTool.name}"`);
4120
5231
  }
4121
- const stringValue = String(value);
4122
- let safeValue;
4123
- if (_ActionExecutor.SHELL_METACHARACTERS.test(stringValue)) {
4124
- safeValue = this.shellEscape(stringValue);
4125
- console.log(_chalk2.default.yellow(` \u26A0 Parameter "${paramName}" contains shell metacharacters, escaped for safety`));
4126
- } else {
4127
- safeValue = stringValue;
4128
- }
5232
+ const safeValue = this.shellEscape(String(value));
5233
+ command = command.replace(new RegExp(`(["'])\\{\\{${paramName}\\}\\}\\1`, "g"), safeValue);
4129
5234
  command = command.replace(new RegExp(`\\{\\{${paramName}\\}\\}`, "g"), safeValue);
4130
5235
  }
4131
5236
  console.log(_chalk2.default.cyan(`
4132
5237
  \u{1F527} Running meta-tool: ${metaTool.name}`));
4133
5238
  console.log(_chalk2.default.gray(` $ ${command}`));
4134
- const result = await runCommand(command, [], this.runtime.workspaceRoot, { shell: true });
4135
- return [`$ ${command}`, result.stdout, result.stderr].filter(Boolean).join("\n");
5239
+ const permissionContext = {
5240
+ tool: "run_command",
5241
+ command,
5242
+ description: `Meta-tool ${metaTool.name}: ${metaTool.description}`
5243
+ };
5244
+ const decision = this.permissionManager.checkPermission(permissionContext);
5245
+ if (decision.reason === "blacklisted" || decision.reason === "mode_restricted" || decision.reason === "pattern_denied" || decision.reason === "not_in_available" || decision.reason === "excluded" || decision.reason === "deny_list" || decision.reason === "session_deny_list" || decision.reason === "project_deny_list" || decision.reason === "user_deny_list") {
5246
+ return `Blocked: Cannot run meta-tool ${metaTool.name} (${decision.reason})`;
5247
+ }
5248
+ if (!decision.allowed) {
5249
+ const hookResult = await this.checkPermissionHook({
5250
+ tool: "run_command",
5251
+ command,
5252
+ args
5253
+ });
5254
+ if (hookResult.blocked) {
5255
+ return `Blocked: ${hookResult.reason}`;
5256
+ }
5257
+ if (hookResult.allowed !== void 0) {
5258
+ await this.permissionManager.recordDecision(permissionContext, hookResult.allowed);
5259
+ if (!hookResult.allowed) {
5260
+ return `Denied: ${_nullishCoalesce(hookResult.reason, () => ( `meta-tool ${metaTool.name}`))}`;
5261
+ }
5262
+ } else {
5263
+ const confirmed = await this.confirmDangerousAction(
5264
+ `Run meta-tool ${metaTool.name}?`,
5265
+ { tool: "run_command", command }
5266
+ );
5267
+ await this.permissionManager.recordDecision(permissionContext, confirmed);
5268
+ if (!confirmed) {
5269
+ return `Skipped running meta-tool ${metaTool.name}`;
5270
+ }
5271
+ }
5272
+ }
5273
+ const result = await _chunkWTB7AFL6cjs.runCommand.call(void 0, command, [], this.runtime.workspaceRoot, {
5274
+ shell: true,
5275
+ timeout: 12e4
5276
+ });
5277
+ const stdout = this.truncateMetaToolOutput(result.stdout);
5278
+ const stderr = this.truncateMetaToolOutput(result.stderr);
5279
+ return [`$ ${command}`, stdout, stderr].filter(Boolean).join("\n");
5280
+ }
5281
+ truncateMetaToolOutput(output) {
5282
+ const limit = 2e5;
5283
+ if (output.length <= limit) {
5284
+ return output;
5285
+ }
5286
+ return `${output.slice(0, limit)}
5287
+ [meta-tool output truncated at ${limit} characters]`;
4136
5288
  }
4137
5289
  applySearchReplaceBlocks(content, blocks) {
4138
5290
  let result = content;
@@ -4227,17 +5379,17 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4227
5379
  score += 2;
4228
5380
  }
4229
5381
  if (score > 0 && (!bestMatch || score > bestMatch.score)) {
4230
- bestMatch = { line: line.trim(), score };
5382
+ bestMatch = { line: line.trim(), originalLine: line, score };
4231
5383
  }
4232
5384
  }
4233
- return bestMatch && bestMatch.score >= 2 ? bestMatch.line : null;
5385
+ return bestMatch && bestMatch.score >= 2 ? bestMatch.originalLine : null;
4234
5386
  }
4235
5387
  /**
4236
5388
  * Colorize raw git diff output with green for additions and red for removals
4237
5389
  */
4238
5390
  colorizeGitDiff(diffOutput) {
4239
- const useTheme = _chunkPGRH5Q77cjs.isThemeInitialized.call(void 0, );
4240
- const theme = useTheme ? _chunkPGRH5Q77cjs.getTheme.call(void 0, ) : null;
5391
+ const useTheme = _chunk2VHB43IXcjs.isThemeInitialized.call(void 0, );
5392
+ const theme = useTheme ? _chunk2VHB43IXcjs.getTheme.call(void 0, ) : null;
4241
5393
  if (!diffOutput || diffOutput === "No diff") {
4242
5394
  return theme ? theme.fg("muted", "No changes") : _chalk2.default.gray("No changes");
4243
5395
  }
@@ -4246,12 +5398,12 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4246
5398
  const colorizedLines = [];
4247
5399
  let additions = 0;
4248
5400
  let deletions = 0;
4249
- const addedColor = _optionalChain([theme, 'optionalAccess', _67 => _67.getColor, 'call', _68 => _68("diffAdded")]) || "#4caf50";
4250
- const removedColor = _optionalChain([theme, 'optionalAccess', _69 => _69.getColor, 'call', _70 => _70("diffRemoved")]) || "#f44336";
4251
- const contextColor = _optionalChain([theme, 'optionalAccess', _71 => _71.getColor, 'call', _72 => _72("diffContext")]) || "#9e9e9e";
4252
- const accentColor = _optionalChain([theme, 'optionalAccess', _73 => _73.getColor, 'call', _74 => _74("accent")]) || "#00bcd4";
4253
- const addedRgb = _chunkPGRH5Q77cjs.hexToRgb.call(void 0, addedColor);
4254
- const removedRgb = _chunkPGRH5Q77cjs.hexToRgb.call(void 0, removedColor);
5401
+ const addedColor = _optionalChain([theme, 'optionalAccess', _110 => _110.getColor, 'call', _111 => _111("diffAdded")]) || "#4caf50";
5402
+ const removedColor = _optionalChain([theme, 'optionalAccess', _112 => _112.getColor, 'call', _113 => _113("diffRemoved")]) || "#f44336";
5403
+ const contextColor = _optionalChain([theme, 'optionalAccess', _114 => _114.getColor, 'call', _115 => _115("diffContext")]) || "#9e9e9e";
5404
+ const accentColor = _optionalChain([theme, 'optionalAccess', _116 => _116.getColor, 'call', _117 => _117("accent")]) || "#00bcd4";
5405
+ const addedRgb = _chunk2VHB43IXcjs.hexToRgb.call(void 0, addedColor);
5406
+ const removedRgb = _chunk2VHB43IXcjs.hexToRgb.call(void 0, removedColor);
4255
5407
  const addBgR = addedRgb ? Math.floor(addedRgb.r * 0.15) : 30;
4256
5408
  const addBgG = addedRgb ? Math.floor(addedRgb.g * 0.2) : 50;
4257
5409
  const addBgB = addedRgb ? Math.floor(addedRgb.b * 0.15) : 30;
@@ -4316,12 +5468,16 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4316
5468
  }
4317
5469
  }
4318
5470
  showDiff(oldContent, newContent, filePath) {
5471
+ console.log(this.formatDiffPreview(oldContent, newContent, filePath));
5472
+ console.log();
5473
+ }
5474
+ formatDiffPreview(oldContent, newContent, filePath) {
4319
5475
  const diff = _diff.diffLines.call(void 0, oldContent, newContent);
4320
5476
  const contextLines = 3;
4321
5477
  const lang = filePath ? detectLanguage(filePath) : "text";
4322
5478
  const shouldHighlight = lang !== "text";
4323
- const useTheme = _chunkPGRH5Q77cjs.isThemeInitialized.call(void 0, );
4324
- const theme = useTheme ? _chunkPGRH5Q77cjs.getTheme.call(void 0, ) : null;
5479
+ const useTheme = _chunk2VHB43IXcjs.isThemeInitialized.call(void 0, );
5480
+ const theme = useTheme ? _chunk2VHB43IXcjs.getTheme.call(void 0, ) : null;
4325
5481
  let additions = 0;
4326
5482
  let deletions = 0;
4327
5483
  for (const part of diff) {
@@ -4332,10 +5488,11 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4332
5488
  const termWidth = process.stdout.columns || 100;
4333
5489
  const addText = additions === 1 ? "1 line" : `${additions} lines`;
4334
5490
  const delText = deletions === 1 ? "1 line" : `${deletions} lines`;
5491
+ const outputLines = [];
4335
5492
  if (theme) {
4336
- console.log(theme.fg("muted", ` Added ${theme.fg("diffAdded", addText)}, removed ${theme.fg("diffRemoved", delText)}`));
5493
+ outputLines.push(theme.fg("muted", ` Added ${theme.fg("diffAdded", addText)}, removed ${theme.fg("diffRemoved", delText)}`));
4337
5494
  } else {
4338
- console.log(_chalk2.default.gray(` Added ${_chalk2.default.green(addText)}, removed ${_chalk2.default.red(delText)}`));
5495
+ outputLines.push(_chalk2.default.gray(` Added ${_chalk2.default.green(addText)}, removed ${_chalk2.default.red(delText)}`));
4339
5496
  }
4340
5497
  const hunks = [];
4341
5498
  let currentHunk = null;
@@ -4418,48 +5575,49 @@ Searching skills: "${query}"${action.category ? ` [${action.category}]` : ""}...
4418
5575
  const removedColor = theme.getColor("diffRemoved");
4419
5576
  const contextColor = theme.getColor("diffContext");
4420
5577
  if (change.type === "add") {
4421
- const addedRgb = _chunkPGRH5Q77cjs.hexToRgb.call(void 0, addedColor);
5578
+ const addedRgb = _chunk2VHB43IXcjs.hexToRgb.call(void 0, addedColor);
4422
5579
  const bgR = addedRgb ? Math.floor(addedRgb.r * 0.15) : 30;
4423
5580
  const bgG = addedRgb ? Math.floor(addedRgb.g * 0.2) : 50;
4424
5581
  const bgB = addedRgb ? Math.floor(addedRgb.b * 0.15) : 30;
4425
5582
  const prefix = _chalk2.default.bgHex(addedColor).black(` ${lineNumStr} + `);
4426
5583
  const content = _chalk2.default.bgRgb(bgR, bgG, bgB)(` ${highlighted} `.padEnd(Math.max(termWidth - 10, change.line.length + 2)));
4427
- console.log(prefix + content);
5584
+ outputLines.push(prefix + content);
4428
5585
  } else if (change.type === "remove") {
4429
- const removedRgb = _chunkPGRH5Q77cjs.hexToRgb.call(void 0, removedColor);
5586
+ const removedRgb = _chunk2VHB43IXcjs.hexToRgb.call(void 0, removedColor);
4430
5587
  const bgR = removedRgb ? Math.floor(removedRgb.r * 0.25) : 60;
4431
5588
  const bgG = removedRgb ? Math.floor(removedRgb.g * 0.15) : 30;
4432
5589
  const bgB = removedRgb ? Math.floor(removedRgb.b * 0.15) : 30;
4433
5590
  const prefix = _chalk2.default.bgHex(removedColor).white(` ${lineNumStr} - `);
4434
5591
  const content = _chalk2.default.bgRgb(bgR, bgG, bgB)(` ${highlighted} `.padEnd(Math.max(termWidth - 10, change.line.length + 2)));
4435
- console.log(prefix + content);
5592
+ outputLines.push(prefix + content);
4436
5593
  } else {
4437
- console.log(_chalk2.default.hex(contextColor)(` ${lineNumStr} `) + ` ${highlighted}`);
5594
+ outputLines.push(_chalk2.default.hex(contextColor)(` ${lineNumStr} `) + ` ${highlighted}`);
4438
5595
  }
4439
5596
  } else {
4440
5597
  if (change.type === "add") {
4441
5598
  const prefix = _chalk2.default.bgGreen.black(` ${lineNumStr} + `);
4442
5599
  const content = _chalk2.default.bgRgb(30, 50, 30)(` ${highlighted} `.padEnd(Math.max(termWidth - 10, change.line.length + 2)));
4443
- console.log(prefix + content);
5600
+ outputLines.push(prefix + content);
4444
5601
  } else if (change.type === "remove") {
4445
5602
  const prefix = _chalk2.default.bgRed.white(` ${lineNumStr} - `);
4446
5603
  const content = _chalk2.default.bgRgb(60, 30, 30)(` ${highlighted} `.padEnd(Math.max(termWidth - 10, change.line.length + 2)));
4447
- console.log(prefix + content);
5604
+ outputLines.push(prefix + content);
4448
5605
  } else {
4449
- console.log(_chalk2.default.gray(` ${lineNumStr} `) + ` ${highlighted}`);
5606
+ outputLines.push(_chalk2.default.gray(` ${lineNumStr} `) + ` ${highlighted}`);
4450
5607
  }
4451
5608
  }
4452
5609
  }
4453
5610
  }
4454
- console.log();
5611
+ return outputLines.join("\n");
4455
5612
  }
4456
- };
5613
+ }, _class3.__initStatic(), _class3);
5614
+
4457
5615
 
4458
5616
 
4459
5617
 
4460
5618
 
4461
5619
 
4462
- exports.getAutoCommitInfo = getAutoCommitInfo; exports.ToolsRegistry = ToolsRegistry; exports.ActionExecutor = ActionExecutor;
5620
+ exports.getAutoCommitInfo = getAutoCommitInfo; exports.WorktreeManager = WorktreeManager; exports.createToolsRegistry = createToolsRegistry; exports.ActionExecutor = ActionExecutor;
4463
5621
  /**
4464
5622
  * @license
4465
5623
  * Copyright 2025 Autohand AI LLC
@@ -4488,6 +5646,13 @@ exports.getAutoCommitInfo = getAutoCommitInfo; exports.ToolsRegistry = ToolsRegi
4488
5646
  *
4489
5647
  * GitHub and GitLab repository browsing capabilities.
4490
5648
  */
5649
+ /**
5650
+ * @license
5651
+ * Copyright 2025 Autohand AI LLC
5652
+ * SPDX-License-Identifier: Apache-2.0
5653
+ *
5654
+ * Project tracker — queries GitHub issues and PRs via gh CLI.
5655
+ */
4491
5656
  /**
4492
5657
  * @license
4493
5658
  * Copyright 2025 Autohand AI LLC