autohand-cli 0.7.14 → 0.8.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 (394) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/AgentRegistry-7LDL5HJH.js +10 -0
  3. package/dist/AgentRegistry-NQCLWABO.cjs +10 -0
  4. package/dist/{AutomodeManager-NGRAO2MH.js → AutomodeManager-MWLKGPZK.js} +2 -0
  5. package/dist/{AutomodeManager-ZKQMBM4T.cjs → AutomodeManager-NYIZNODK.cjs} +3 -1
  6. package/dist/CommunitySkillsCache-6QPRMTJO.js +8 -0
  7. package/dist/CommunitySkillsCache-GTQMOCCO.cjs +8 -0
  8. package/dist/{GitHubRegistryFetcher-US2JJID4.js → GitHubRegistryFetcher-6JQ5JEDZ.js} +1 -0
  9. package/dist/{GitHubRegistryFetcher-K744NNAJ.cjs → GitHubRegistryFetcher-S7QFUEKV.cjs} +1 -0
  10. package/dist/HookManager-Q2KYMCP4.cjs +7 -0
  11. package/dist/HookManager-TTP4Y6DC.js +7 -0
  12. package/dist/ImportWizard-IWVPRKFF.cjs +466 -0
  13. package/dist/ImportWizard-KASGQPUY.js +466 -0
  14. package/dist/McpClientManager-7RM6YT35.js +8 -0
  15. package/dist/McpClientManager-RKD7C6OY.cjs +8 -0
  16. package/dist/MemoryManager-GUNLRP5S.js +8 -0
  17. package/dist/MemoryManager-TNSGKDKX.cjs +8 -0
  18. package/dist/PermissionManager-2GO5PQ6M.cjs +11 -0
  19. package/dist/{PermissionManager-U5OMGR3L.js → PermissionManager-K7UWSNB6.js} +4 -3
  20. package/dist/ProjectProfiler-UMJJSOCE.js +194 -0
  21. package/dist/ProjectProfiler-ZDWR2ODG.cjs +194 -0
  22. package/dist/ProviderFactory-EFFQBRQ6.cjs +9 -0
  23. package/dist/ProviderFactory-S3LWTQQC.js +9 -0
  24. package/dist/SessionManager-FEUAU3ZJ.cjs +10 -0
  25. package/dist/SessionManager-IKWAK2PI.js +10 -0
  26. package/dist/SkillsRegistry-GDEGFP6O.cjs +9 -0
  27. package/dist/SkillsRegistry-SI5RUHQ4.js +9 -0
  28. package/dist/SubAgent-I75HELJG.js +11 -0
  29. package/dist/SubAgent-K3QP6WHC.cjs +11 -0
  30. package/dist/{SyncApiClient-AYXYSOJM.js → SyncApiClient-LVIO4C2S.js} +1 -0
  31. package/dist/{SyncApiClient-ID3KXEMA.cjs → SyncApiClient-ZNYMT36M.cjs} +1 -0
  32. package/dist/about-B2AGTV6N.js +12 -0
  33. package/dist/about-V2HWEZZO.cjs +12 -0
  34. package/dist/actionExecutor-6XCVL2SJ.js +19 -0
  35. package/dist/actionExecutor-YRUJNB5G.cjs +19 -0
  36. package/dist/add-dir-7FBQ5IFV.js +10 -0
  37. package/dist/add-dir-ALBSYRV3.cjs +10 -0
  38. package/dist/agents/builtin/code-cleaner.md +14 -0
  39. package/dist/agents/builtin/docs-writer.md +14 -0
  40. package/dist/agents/builtin/researcher.md +14 -0
  41. package/dist/agents/builtin/reviewer.md +15 -0
  42. package/dist/agents/builtin/tester.md +15 -0
  43. package/dist/agents/builtin/todo-resolver.md +15 -0
  44. package/dist/agents-FCGEWTA3.cjs +12 -0
  45. package/dist/agents-FENGUSJD.js +12 -0
  46. package/dist/agents-new-FU3O55CO.js +14 -0
  47. package/dist/agents-new-SAFTJ7TK.cjs +14 -0
  48. package/dist/assets/icon.png +0 -0
  49. package/dist/automode-CYLGXQ4A.cjs +10 -0
  50. package/dist/automode-O7G3DUYN.js +10 -0
  51. package/dist/{cc-UTTLESTY.js → cc-7LEIJ3KF.js} +1 -0
  52. package/dist/{cc-2W6M7J45.cjs → cc-Q5MM4AWC.cjs} +1 -0
  53. package/dist/{chunk-N4ZSG6JJ.cjs → chunk-22D2CNTP.cjs} +2 -2
  54. package/dist/chunk-24QIWILL.js +51 -0
  55. package/dist/{chunk-MYNHJHDZ.js → chunk-2AA5MFES.js} +1 -1
  56. package/dist/{chunk-KWRUQRXR.js → chunk-2ELK5DMH.js} +44 -10
  57. package/dist/chunk-2JYIR3EC.cjs +1176 -0
  58. package/dist/{chunk-CRQKDBLD.js → chunk-2RIAPTET.js} +90 -66
  59. package/dist/{chunk-TSY7JHIV.cjs → chunk-33A755XB.cjs} +2 -2
  60. package/dist/chunk-3OEDGIFW.js +42 -0
  61. package/dist/{chunk-P5VDZ6PV.js → chunk-3PDTTAKJ.js} +1 -1
  62. package/dist/{chunk-ULMPJUJW.cjs → chunk-3WCOFXQS.cjs} +23 -23
  63. package/dist/{chunk-PDKNHU5G.cjs → chunk-4HKTYHNL.cjs} +22 -16
  64. package/dist/{chunk-Z4J4W6YQ.cjs → chunk-4JNNTOGF.cjs} +2 -48
  65. package/dist/chunk-55B6SBHK.js +260 -0
  66. package/dist/chunk-5DDDUUBM.cjs +29 -0
  67. package/dist/{chunk-TQB222ZB.js → chunk-5EIEWVYX.js} +2 -2
  68. package/dist/{chunk-SMHY3Q7B.cjs → chunk-5GGX6WNY.cjs} +54 -22
  69. package/dist/{chunk-3S4DEIJP.cjs → chunk-5IXII4HX.cjs} +2 -2
  70. package/dist/{chunk-3KBBARKO.js → chunk-5OBNULPU.js} +85 -28
  71. package/dist/{chunk-VVBBEYTH.cjs → chunk-5YJG6H6P.cjs} +10 -10
  72. package/dist/{chunk-PKOAXQKW.cjs → chunk-63WXWFDI.cjs} +11 -11
  73. package/dist/{chunk-DSKVMFRM.cjs → chunk-643VRA5S.cjs} +12 -4
  74. package/dist/{chunk-L5ZFPWHY.js → chunk-6OYHF6MF.js} +12 -4
  75. package/dist/chunk-7GDVDSNI.js +1176 -0
  76. package/dist/chunk-7QEE6SW6.cjs +260 -0
  77. package/dist/chunk-7UOUW76C.js +603 -0
  78. package/dist/{chunk-SZP4ULM5.cjs → chunk-AFN7LH5N.cjs} +17 -17
  79. package/dist/chunk-AHD5JJ6F.cjs +78 -0
  80. package/dist/{chunk-WLTVF77A.js → chunk-ALYU6VTM.js} +1 -1
  81. package/dist/{chunk-BRXIEKJ3.cjs → chunk-AMT2UZBI.cjs} +5 -5
  82. package/dist/{chunk-SFNT5DYE.cjs → chunk-BT35E7NE.cjs} +4 -4
  83. package/dist/{chunk-NUHYCFHW.cjs → chunk-BVKXEQVG.cjs} +54 -65
  84. package/dist/chunk-CDMGQR4L.cjs +4470 -0
  85. package/dist/chunk-CNBKZEX5.cjs +109 -0
  86. package/dist/{chunk-GD4AFYJ3.js → chunk-CVVEYUFR.js} +1 -1
  87. package/dist/chunk-CWALFEGU.js +58 -0
  88. package/dist/{chunk-MTALRU7R.cjs → chunk-D3YCFT5O.cjs} +3 -3
  89. package/dist/{chunk-CH4SPVFD.cjs → chunk-D6VG7B5X.cjs} +9 -3
  90. package/dist/{chunk-TOTDRAWG.js → chunk-DH7DKCUL.js} +1 -1
  91. package/dist/{chunk-RFNCTE4V.cjs → chunk-DLG43ZJ7.cjs} +2 -2
  92. package/dist/chunk-DN573ME7.cjs +1675 -0
  93. package/dist/{chunk-63BXZQZW.js → chunk-E23CMMNJ.js} +20 -4
  94. package/dist/{chunk-4HA7IHLJ.cjs → chunk-EEGK5DYE.cjs} +32 -16
  95. package/dist/{chunk-DTFR3WD6.js → chunk-EF4LKUQY.js} +1 -1
  96. package/dist/{chunk-PWLLLJHU.js → chunk-EGFT4PGW.js} +3 -1
  97. package/dist/{chunk-S47TCZDL.js → chunk-EIU7K7CM.js} +7 -7
  98. package/dist/{chunk-BISFR6ZL.js → chunk-EPNYD4NV.js} +1 -1
  99. package/dist/chunk-EZMINVLU.js +123 -0
  100. package/dist/{chunk-LYMTYC67.js → chunk-F23EVNJU.js} +2 -2
  101. package/dist/chunk-FHK7UDOJ.cjs +42 -0
  102. package/dist/chunk-FMB3TSWP.cjs +218 -0
  103. package/dist/{chunk-XBUMKEFN.cjs → chunk-FPAE6ORV.cjs} +91 -34
  104. package/dist/{chunk-DEAEO7RI.js → chunk-FYZ67R4R.js} +1 -1
  105. package/dist/{chunk-6SHHB2VD.js → chunk-G7SZIOHF.js} +2 -2
  106. package/dist/{chunk-FB6JWNJS.js → chunk-GBHDROGL.js} +54 -65
  107. package/dist/chunk-GCHELXLO.js +131 -0
  108. package/dist/{chunk-XPOHYKR3.js → chunk-GHSBZ3YB.js} +2 -2
  109. package/dist/chunk-GLBAF54O.js +218 -0
  110. package/dist/chunk-GO3N7LRW.cjs +131 -0
  111. package/dist/{chunk-Y2ZSH3YF.cjs → chunk-H6ZGZEBG.cjs} +57 -23
  112. package/dist/{chunk-DSCQPWUB.cjs → chunk-HA7OAVOB.cjs} +15 -15
  113. package/dist/{chunk-NMWEDN4Z.js → chunk-HFMLWH7B.js} +108 -0
  114. package/dist/{chunk-D2XFTCRP.js → chunk-HQ7YZKXE.js} +1 -1
  115. package/dist/{chunk-L42HTMMR.cjs → chunk-HTLINWX6.cjs} +2 -2
  116. package/dist/chunk-IETRBBMP.cjs +603 -0
  117. package/dist/chunk-IQ5RXU6O.js +1675 -0
  118. package/dist/{chunk-GVZPIQWB.js → chunk-ITB3FS72.js} +11 -5
  119. package/dist/{chunk-B6EBHCK2.cjs → chunk-IUMJYXBX.cjs} +6 -6
  120. package/dist/{chunk-ZBIBLOZL.js → chunk-IVM5F2AE.js} +500 -317
  121. package/dist/{chunk-GRSVQ5YZ.js → chunk-IWVQ2EW3.js} +44 -12
  122. package/dist/chunk-JJWCQLOU.cjs +59 -0
  123. package/dist/{chunk-KXAAEROY.js → chunk-JMFDD7IZ.js} +2 -2
  124. package/dist/chunk-JSBRDJBE.js +30 -0
  125. package/dist/chunk-LJFUXC56.cjs +123 -0
  126. package/dist/chunk-LL3PQ2U6.js +4470 -0
  127. package/dist/chunk-LQ4LQQG6.cjs +27 -0
  128. package/dist/chunk-LQGVEP3E.js +109 -0
  129. package/dist/{chunk-425MT6Y5.cjs → chunk-LVE6Z5SL.cjs} +9 -9
  130. package/dist/{chunk-XL77XYI2.cjs → chunk-LXDOQTXQ.cjs} +4 -4
  131. package/dist/{chunk-BG4OQUKP.js → chunk-MBBY4ZIK.js} +1 -1
  132. package/dist/{chunk-ZXIQCYYV.cjs → chunk-MGMXR67S.cjs} +9 -9
  133. package/dist/{chunk-FHUNAB2K.cjs → chunk-MHLE6AVN.cjs} +33 -6
  134. package/dist/chunk-MHSDHPC4.cjs +58 -0
  135. package/dist/chunk-MUBW5UDH.cjs +55 -0
  136. package/dist/{chunk-MNSTWHK3.cjs → chunk-MVWOQBCC.cjs} +11 -11
  137. package/dist/chunk-N254NRHT.cjs +30 -0
  138. package/dist/{chunk-SRLY7K6J.js → chunk-OBLIITWJ.js} +2 -2
  139. package/dist/{chunk-SIGWDEPS.cjs → chunk-OI7OIGNB.cjs} +10 -10
  140. package/dist/{chunk-V7YTCNMN.cjs → chunk-OPR34VHL.cjs} +5 -5
  141. package/dist/chunk-OUHQZFN4.js +78 -0
  142. package/dist/{chunk-HMRDNRTH.js → chunk-PEC45WYS.js} +2 -2
  143. package/dist/{chunk-OSUWEUZE.js → chunk-PUOE5BCN.js} +1 -1
  144. package/dist/chunk-Q2VYSHWU.js +59 -0
  145. package/dist/chunk-Q3MJ6CYS.cjs +193 -0
  146. package/dist/{chunk-QRGPAUST.js → chunk-Q5RN7RXC.js} +2 -2
  147. package/dist/{chunk-43XS26AQ.cjs → chunk-Q5RX3XGB.cjs} +4 -4
  148. package/dist/chunk-QCLYBIMM.cjs +51 -0
  149. package/dist/chunk-QMAKTSZB.cjs +48 -0
  150. package/dist/chunk-QT2VZNFA.js +29 -0
  151. package/dist/{chunk-3XJD56Z4.js → chunk-QUFAULH7.js} +9 -3
  152. package/dist/{chunk-RJP3SZ7Q.cjs → chunk-RD5XAJR2.cjs} +492 -309
  153. package/dist/chunk-RGR6ME5J.cjs +844 -0
  154. package/dist/{chunk-EOGKE5GD.cjs → chunk-RKJTGGMU.cjs} +221 -126
  155. package/dist/{chunk-NMGF2KUN.js → chunk-RO46YAPI.js} +1 -1
  156. package/dist/{chunk-2U5HFVRO.cjs → chunk-RVUQKMXX.cjs} +108 -0
  157. package/dist/chunk-S52YW5ZQ.js +844 -0
  158. package/dist/{chunk-ZLOTP56B.cjs → chunk-S6BDWWUG.cjs} +5 -5
  159. package/dist/{chunk-6DWXHBAY.js → chunk-SAHBLB3E.js} +222 -127
  160. package/dist/chunk-SALLHB2I.js +27 -0
  161. package/dist/{chunk-GIZL57FE.cjs → chunk-SEKD5FH3.cjs} +3 -1
  162. package/dist/{chunk-DZHR34H6.cjs → chunk-SHFA46CS.cjs} +8 -8
  163. package/dist/{chunk-MILZEEUV.js → chunk-SIHRD34Z.js} +2 -2
  164. package/dist/{chunk-BPTBKO7D.js → chunk-SO3QQJAZ.js} +216 -36
  165. package/dist/{chunk-HSPWX4Z2.cjs → chunk-SRQW3B6J.cjs} +223 -43
  166. package/dist/{chunk-MY3TZER2.js → chunk-T63AMO6H.js} +1 -1
  167. package/dist/{chunk-X765A7J5.js → chunk-TERCG25S.js} +1 -1
  168. package/dist/{chunk-WOGJXDBU.cjs → chunk-TFSRRZWP.cjs} +3 -3
  169. package/dist/{chunk-RRZS5A53.js → chunk-TQHOVHRS.js} +1 -1
  170. package/dist/{chunk-JHOQABEF.js → chunk-TWEKBHUO.js} +5 -5
  171. package/dist/chunk-U3WDY42C.cjs +42 -0
  172. package/dist/{chunk-CKN2BLHK.cjs → chunk-UBS46QL3.cjs} +2 -2
  173. package/dist/{chunk-H3GBSPK5.js → chunk-UGTFKUW4.js} +14 -6
  174. package/dist/chunk-UJTCTTUF.cjs +271 -0
  175. package/dist/{chunk-RUZB43HU.cjs → chunk-UTI6ZQEY.cjs} +22 -14
  176. package/dist/{chunk-OLG7LZBD.js → chunk-VG34MG2U.js} +1 -1
  177. package/dist/{chunk-ZKZRFH37.cjs → chunk-VJYPP6PP.cjs} +6 -6
  178. package/dist/{chunk-YHGTBPEC.js → chunk-VNQ5GL34.js} +1 -1
  179. package/dist/{chunk-XDVG3NM4.js → chunk-W3X6PAC7.js} +2 -48
  180. package/dist/{chunk-FK2DVRPJ.js → chunk-WFUUXADU.js} +2 -2
  181. package/dist/{chunk-R5OO7MEB.cjs → chunk-WGTJOIB7.cjs} +22 -22
  182. package/dist/{chunk-VHBUKGRG.js → chunk-WJDPVW7T.js} +4 -4
  183. package/dist/chunk-WNUVPKBW.js +42 -0
  184. package/dist/{chunk-EV53SLSB.cjs → chunk-WPVWQSL7.cjs} +4 -4
  185. package/dist/chunk-WQ3VJXZB.js +118 -0
  186. package/dist/chunk-WTNBX2JO.js +271 -0
  187. package/dist/chunk-XAV24VYN.js +48 -0
  188. package/dist/chunk-XDLH4EDL.cjs +118 -0
  189. package/dist/{chunk-U7CZFKPL.cjs → chunk-XMNHZRUB.cjs} +2 -2
  190. package/dist/chunk-XUDSXGGV.cjs +1822 -0
  191. package/dist/{chunk-WQUQ5JMM.js → chunk-XWASJ2QL.js} +4 -4
  192. package/dist/chunk-Y2SXUCNJ.js +55 -0
  193. package/dist/{chunk-AIH6GUGB.cjs → chunk-YDCDGTK6.cjs} +5 -5
  194. package/dist/chunk-YFXTE422.cjs +92 -0
  195. package/dist/chunk-YKS55CMT.js +1822 -0
  196. package/dist/{chunk-KC5FPUOF.cjs → chunk-YRLYSQEQ.cjs} +2 -2
  197. package/dist/{chunk-JWPI6O5Z.js → chunk-YS34SVY5.js} +31 -4
  198. package/dist/{chunk-FEVHH525.cjs → chunk-YYB42DCU.cjs} +4 -4
  199. package/dist/chunk-ZK6HOR62.js +92 -0
  200. package/dist/{chunk-BHV7CBNT.js → chunk-ZSE42BRE.js} +1 -1
  201. package/dist/clear-ES5WCZRF.cjs +12 -0
  202. package/dist/clear-J7XS6T5W.js +12 -0
  203. package/dist/completion-XQTDTJLK.cjs +14 -0
  204. package/dist/completion-XR6ZONJQ.js +14 -0
  205. package/dist/config-2TB3A55J.js +18 -0
  206. package/dist/config-RDMVIV26.cjs +18 -0
  207. package/dist/constants-6CPCJ3DY.cjs +21 -0
  208. package/dist/{constants-V6J54N3X.js → constants-UFM5B232.js} +2 -1
  209. package/dist/{defaultHooks-WLMRQUXG.cjs → defaultHooks-RCXPHF4M.cjs} +3 -1
  210. package/dist/{defaultHooks-R56VYG7I.js → defaultHooks-RDRMER3Z.js} +2 -0
  211. package/dist/export-EWAYH353.cjs +12 -0
  212. package/dist/export-ZWA6XGVS.js +12 -0
  213. package/dist/extractSessionMemories-SDW2MVBQ.cjs +7 -0
  214. package/dist/extractSessionMemories-V7K42ZHW.js +7 -0
  215. package/dist/feedback-5RV6ODW4.js +15 -0
  216. package/dist/feedback-ZPITHFJR.cjs +15 -0
  217. package/dist/filesystem-3SGCW2BF.js +10 -0
  218. package/dist/filesystem-MCFXJQ6R.cjs +10 -0
  219. package/dist/formatters-6K7QVWQL.cjs +10 -0
  220. package/dist/formatters-DQHO5I36.js +10 -0
  221. package/dist/{help-LKKQU2TN.js → help-I5GRCA3S.js} +3 -2
  222. package/dist/help-X52PZM24.cjs +12 -0
  223. package/dist/history-4WIOZ4TW.cjs +14 -0
  224. package/dist/{history-AV4XBFRK.js → history-OCHJBJW7.js} +3 -2
  225. package/dist/hooks-IAVTXUAI.cjs +13 -0
  226. package/dist/hooks-YF6HL23E.js +13 -0
  227. package/dist/{i18n-BSAPXM56.js → i18n-KHBXUALK.js} +2 -1
  228. package/dist/i18n-MVQIAZWS.cjs +33 -0
  229. package/dist/ide-4R3BEBIS.js +12 -0
  230. package/dist/ide-C7WSPQTR.cjs +12 -0
  231. package/dist/import-2ICSKDL7.cjs +10 -0
  232. package/dist/import-EAAX5HJR.js +170 -0
  233. package/dist/import-KRVVYJCZ.js +10 -0
  234. package/dist/import-PQJPNXA4.cjs +170 -0
  235. package/dist/index.cjs +7503 -11251
  236. package/dist/index.js +8735 -12483
  237. package/dist/init-6K3NRDOM.js +10 -0
  238. package/dist/init-AOUGGITS.cjs +10 -0
  239. package/dist/language-Q7YFDVSR.cjs +18 -0
  240. package/dist/language-Y6ZC7LET.js +18 -0
  241. package/dist/{lint-44UQJ673.cjs → lint-D5UOJWIK.cjs} +1 -0
  242. package/dist/{lint-TA2ZHVLM.js → lint-NJPZWVN2.js} +1 -0
  243. package/dist/{localProjectPermissions-WQYMGI42.js → localProjectPermissions-N77HA3XK.js} +3 -2
  244. package/dist/localProjectPermissions-UFSMNTBJ.cjs +18 -0
  245. package/dist/login-6OAH2NEH.cjs +20 -0
  246. package/dist/login-DL3377MD.js +20 -0
  247. package/dist/logout-ELQBUMTU.cjs +18 -0
  248. package/dist/logout-TLYA5W45.js +18 -0
  249. package/dist/mcp-BHOIBYUB.js +18 -0
  250. package/dist/mcp-TNUEXR5T.cjs +18 -0
  251. package/dist/{mcp-install-2KVKRAMQ.cjs → mcp-install-GROTZHAW.cjs} +26 -14
  252. package/dist/{mcp-install-77UXRN6R.js → mcp-install-KSADVDBE.js} +21 -9
  253. package/dist/memory-6DRFA43C.js +10 -0
  254. package/dist/memory-IORZE6WF.cjs +10 -0
  255. package/dist/message-JUBOK2VU.js +9 -0
  256. package/dist/message-ZJ5AYAMT.cjs +9 -0
  257. package/dist/model-CJPSPGIC.cjs +10 -0
  258. package/dist/model-MQXC56ES.js +10 -0
  259. package/dist/new-7D2B7IWM.cjs +12 -0
  260. package/dist/new-7VYM36RC.js +12 -0
  261. package/dist/{patch-BAAQIYSW.js → patch-5F6VBIT3.js} +2 -0
  262. package/dist/{patch-J32X2QQP.cjs → patch-MOD7QC3D.cjs} +3 -1
  263. package/dist/permissions-MM77OSFO.js +13 -0
  264. package/dist/permissions-W2F62DJ6.cjs +13 -0
  265. package/dist/{plan-JFGNRL2S.js → plan-G5CEKJI4.js} +1 -0
  266. package/dist/{plan-B3CW5DXJ.cjs → plan-QKOHE3LH.cjs} +1 -0
  267. package/dist/quit-7D2RDGTD.cjs +10 -0
  268. package/dist/quit-PKBSEJOL.js +10 -0
  269. package/dist/registry-A5XLMQVC.cjs +1828 -0
  270. package/dist/registry-WQLWHOLY.js +1828 -0
  271. package/dist/resume-FBKXSDOA.js +13 -0
  272. package/dist/resume-KLPDYPWQ.cjs +13 -0
  273. package/dist/search-7RNYTCNO.js +17 -0
  274. package/dist/search-UESMQZC3.cjs +17 -0
  275. package/dist/{session-T3TAZ5ZU.cjs → session-BSU2L5UI.cjs} +1 -0
  276. package/dist/{session-H5QWKE5E.js → session-SZMRN5KG.js} +1 -0
  277. package/dist/sessions-TSSUFWIJ.cjs +10 -0
  278. package/dist/sessions-WAXBUQTU.js +10 -0
  279. package/dist/settings-D6JXX5RG.js +30 -0
  280. package/dist/settings-RKYGXKDG.cjs +30 -0
  281. package/dist/share-GLX4YHS4.cjs +14 -0
  282. package/dist/share-U2M2KBFJ.js +14 -0
  283. package/dist/skills-63QLZMUO.cjs +14 -0
  284. package/dist/{skills-LJZA6PVJ.js → skills-BAMMXP3Q.js} +3 -2
  285. package/dist/{skills-install-MQINL3EC.js → skills-install-QNQWC2MV.js} +99 -28
  286. package/dist/{skills-install-IKJZN4G2.cjs → skills-install-UMK5H3SO.cjs} +107 -36
  287. package/dist/skills-new-NYKNHJHV.cjs +15 -0
  288. package/dist/skills-new-NZFGFKML.js +15 -0
  289. package/dist/slashCommands-EJ23C3Z4.cjs +69 -0
  290. package/dist/slashCommands-JQIL4EWX.js +69 -0
  291. package/dist/status-BKC7GBNQ.js +11 -0
  292. package/dist/status-FU3CPJWQ.cjs +11 -0
  293. package/dist/sync-3IEIHXIP.cjs +18 -0
  294. package/dist/sync-7JMZVEQD.cjs +40 -0
  295. package/dist/{sync-EXYX7HXW.js → sync-KWX67OUN.js} +3 -2
  296. package/dist/sync-YVPFT7SL.js +18 -0
  297. package/dist/tasks-5FPBIFLC.js +9 -0
  298. package/dist/tasks-TXGKGNH6.cjs +9 -0
  299. package/dist/team-GVK5L73L.cjs +9 -0
  300. package/dist/team-RWIKCLTG.js +9 -0
  301. package/dist/teammate-3C4MLRGH.js +139 -0
  302. package/dist/teammate-7C3UDQSH.cjs +139 -0
  303. package/dist/theme-A2CEHI7W.js +18 -0
  304. package/dist/theme-LNOQOVR4.cjs +18 -0
  305. package/dist/ui/questionModal.cjs +7 -25
  306. package/dist/ui/questionModal.js +6 -24
  307. package/dist/undo-F2IZJQUV.js +10 -0
  308. package/dist/undo-QEV42XLU.cjs +10 -0
  309. package/dist/update-TVAJMMBC.js +82 -0
  310. package/dist/update-Z6BIIQDC.cjs +82 -0
  311. package/package.json +9 -3
  312. package/dist/CommunitySkillsCache-ILWHWE5P.js +0 -7
  313. package/dist/CommunitySkillsCache-KHC6RUJW.cjs +0 -7
  314. package/dist/HookManager-X47HCM5G.cjs +0 -6
  315. package/dist/HookManager-ZXKHCD7U.js +0 -6
  316. package/dist/MemoryManager-6ZT7IDO5.cjs +0 -7
  317. package/dist/MemoryManager-AJGS5AKB.js +0 -7
  318. package/dist/PermissionManager-HG6W2DGU.cjs +0 -10
  319. package/dist/SessionManager-BJ2G6VV4.cjs +0 -9
  320. package/dist/SessionManager-ENPGYK5J.js +0 -9
  321. package/dist/SkillsRegistry-6ZFOCT25.cjs +0 -8
  322. package/dist/SkillsRegistry-C2SHOZ5D.js +0 -8
  323. package/dist/about-3BJTNSLK.js +0 -11
  324. package/dist/about-EABQNJGV.cjs +0 -11
  325. package/dist/add-dir-7FD4DMDA.cjs +0 -9
  326. package/dist/add-dir-LOYJ4YB5.js +0 -9
  327. package/dist/agents-2Y6ASV7C.js +0 -10
  328. package/dist/agents-UOSPKLQL.cjs +0 -10
  329. package/dist/agents-new-23NSGAM5.js +0 -13
  330. package/dist/agents-new-WI2EL7IJ.cjs +0 -13
  331. package/dist/automode-LGWTY3UX.js +0 -9
  332. package/dist/automode-WLBQ7MN7.cjs +0 -9
  333. package/dist/chunk-5UBW2BGC.js +0 -33
  334. package/dist/chunk-I6DBWNLN.cjs +0 -169
  335. package/dist/chunk-IZBCMJHJ.cjs +0 -33
  336. package/dist/completion-7WGMHKOR.cjs +0 -13
  337. package/dist/completion-KH33NSGP.js +0 -13
  338. package/dist/constants-RBQTR32A.cjs +0 -20
  339. package/dist/export-3QN3IH7A.js +0 -11
  340. package/dist/export-BI54X3MP.cjs +0 -11
  341. package/dist/feedback-CI4OIPOS.cjs +0 -14
  342. package/dist/feedback-GFPL5STE.js +0 -14
  343. package/dist/formatters-N5IJKYZY.cjs +0 -8
  344. package/dist/formatters-UG6VZJJ5.js +0 -8
  345. package/dist/help-CWMUGD3V.cjs +0 -11
  346. package/dist/history-73VBEMSI.cjs +0 -13
  347. package/dist/hooks-62UDQBGH.cjs +0 -12
  348. package/dist/hooks-XORDJD5X.js +0 -12
  349. package/dist/i18n-X2IU2EZD.cjs +0 -32
  350. package/dist/ide-RPKZALQV.js +0 -11
  351. package/dist/ide-YMNXJB6A.cjs +0 -11
  352. package/dist/init-J5HR4R7U.js +0 -9
  353. package/dist/init-JCC7RVMC.cjs +0 -9
  354. package/dist/language-AZISJCEZ.js +0 -16
  355. package/dist/language-F65RA6FZ.cjs +0 -16
  356. package/dist/localProjectPermissions-2EATUDZM.cjs +0 -17
  357. package/dist/login-5HLPMECE.js +0 -18
  358. package/dist/login-ISWYYBXP.cjs +0 -18
  359. package/dist/logout-3EKZM5J3.cjs +0 -16
  360. package/dist/logout-GE7TSZ24.js +0 -16
  361. package/dist/mcp-EW64QRFA.cjs +0 -15
  362. package/dist/mcp-VHS7AMF2.js +0 -15
  363. package/dist/memory-2I473RU3.js +0 -9
  364. package/dist/memory-JZ6NPSP3.cjs +0 -9
  365. package/dist/model-GXZLARPT.js +0 -9
  366. package/dist/model-Y274DBDO.cjs +0 -9
  367. package/dist/new-BG5VIGZ7.cjs +0 -9
  368. package/dist/new-YXFDQOA7.js +0 -9
  369. package/dist/permissions-QILEAGBP.cjs +0 -12
  370. package/dist/permissions-WVEOVMWO.js +0 -12
  371. package/dist/quit-NC32OEJG.cjs +0 -9
  372. package/dist/quit-WRRIGU33.js +0 -9
  373. package/dist/resume-GJIKIDPR.cjs +0 -12
  374. package/dist/resume-RMJNCAOK.js +0 -12
  375. package/dist/search-UIWIXB73.js +0 -14
  376. package/dist/search-WQNXDA2E.cjs +0 -14
  377. package/dist/sessions-HPFX2GDD.js +0 -9
  378. package/dist/sessions-SAQU6MFA.cjs +0 -9
  379. package/dist/share-2WH5ZVOO.cjs +0 -13
  380. package/dist/share-PSSWWVV5.js +0 -13
  381. package/dist/skills-YTYGART7.cjs +0 -13
  382. package/dist/skills-new-3WCU3CWB.js +0 -14
  383. package/dist/skills-new-O5LFVFZU.cjs +0 -14
  384. package/dist/slashCommands-7IRDOXOQ.cjs +0 -55
  385. package/dist/slashCommands-C6CAQA25.js +0 -55
  386. package/dist/status-4EDV2LSY.cjs +0 -10
  387. package/dist/status-NU7TJDCE.js +0 -10
  388. package/dist/sync-3GFSEIAZ.js +0 -16
  389. package/dist/sync-6M3WRKMH.cjs +0 -39
  390. package/dist/sync-CQNQDNTJ.cjs +0 -16
  391. package/dist/theme-EMJGULMI.cjs +0 -16
  392. package/dist/theme-FGDSXNU3.js +0 -16
  393. package/dist/undo-CTXQYE7C.cjs +0 -9
  394. package/dist/undo-HX2ZMECP.js +0 -9
@@ -0,0 +1,1828 @@
1
+ import {
2
+ AUTOHAND_PATHS
3
+ } from "./chunk-EGFT4PGW.js";
4
+ import "./chunk-JSBRDJBE.js";
5
+
6
+ // src/import/importers/ClaudeImporter.ts
7
+ import path2 from "path";
8
+ import fse2 from "fs-extra";
9
+
10
+ // src/import/importers/BaseImporter.ts
11
+ import os from "os";
12
+ import path from "path";
13
+ import crypto from "crypto";
14
+ import fse from "fs-extra";
15
+ var BaseImporter = class {
16
+ // ---------------------------------------------------------------
17
+ // Resolved home path
18
+ // ---------------------------------------------------------------
19
+ /**
20
+ * Expands a `~/` prefix to the user's home directory.
21
+ * Returns absolute paths unchanged.
22
+ */
23
+ get resolvedHomePath() {
24
+ if (this.homePath.startsWith("~/") || this.homePath === "~") {
25
+ return path.join(os.homedir(), this.homePath.slice(2));
26
+ }
27
+ return this.homePath;
28
+ }
29
+ // ---------------------------------------------------------------
30
+ // Detection
31
+ // ---------------------------------------------------------------
32
+ /**
33
+ * Checks whether this agent's data directory exists on disk.
34
+ */
35
+ async detect() {
36
+ return fse.pathExists(this.resolvedHomePath);
37
+ }
38
+ // ---------------------------------------------------------------
39
+ // JSONL reader
40
+ // ---------------------------------------------------------------
41
+ /**
42
+ * Reads a JSONL file and returns an array of parsed records.
43
+ * Blank lines and malformed JSON lines are silently skipped.
44
+ */
45
+ async readJsonlFile(filePath) {
46
+ const content = await fse.readFile(filePath, "utf-8");
47
+ const records = [];
48
+ for (const line of content.split("\n")) {
49
+ const trimmed = line.trim();
50
+ if (!trimmed) continue;
51
+ try {
52
+ records.push(JSON.parse(trimmed));
53
+ } catch {
54
+ }
55
+ }
56
+ return records;
57
+ }
58
+ // ---------------------------------------------------------------
59
+ // Retry with exponential backoff
60
+ // ---------------------------------------------------------------
61
+ /**
62
+ * Retries `fn` up to `maxRetries` times with exponential backoff.
63
+ * Throws the last error if all retries are exhausted.
64
+ */
65
+ async withRetry(fn, maxRetries = 3, baseDelay = 1e3) {
66
+ let lastError;
67
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
68
+ try {
69
+ return await fn();
70
+ } catch (err) {
71
+ lastError = err instanceof Error ? err : new Error(String(err));
72
+ if (attempt < maxRetries - 1) {
73
+ await this.delay(baseDelay * Math.pow(2, attempt));
74
+ }
75
+ }
76
+ }
77
+ throw lastError;
78
+ }
79
+ // ---------------------------------------------------------------
80
+ // Session writing
81
+ // ---------------------------------------------------------------
82
+ /**
83
+ * Creates a new Autohand session directory with metadata and conversation data.
84
+ * Returns the generated session ID, or `null` if the session was already imported
85
+ * (deduplication by source + originalId).
86
+ */
87
+ async writeAutohandSession(opts) {
88
+ if (await this.isAlreadyImported(opts.source, opts.originalId)) {
89
+ return null;
90
+ }
91
+ const timestamp = Date.now();
92
+ const uuid = crypto.randomUUID();
93
+ const sessionId = `${uuid}-${timestamp}`;
94
+ const sessionDir = path.join(AUTOHAND_PATHS.sessions, sessionId);
95
+ await fse.ensureDir(sessionDir);
96
+ const metadata = {
97
+ sessionId,
98
+ createdAt: opts.createdAt,
99
+ lastActiveAt: opts.closedAt ?? opts.createdAt,
100
+ closedAt: opts.closedAt,
101
+ projectPath: opts.projectPath,
102
+ projectName: opts.projectName,
103
+ model: opts.model,
104
+ messageCount: opts.messages.length,
105
+ summary: opts.summary,
106
+ status: opts.status ?? "completed",
107
+ importedFrom: {
108
+ source: opts.source,
109
+ originalId: opts.originalId,
110
+ importedAt: (/* @__PURE__ */ new Date()).toISOString()
111
+ }
112
+ };
113
+ await fse.writeJson(path.join(sessionDir, "metadata.json"), metadata, { spaces: 2 });
114
+ const jsonl = opts.messages.map((msg) => JSON.stringify(msg)).join("\n") + "\n";
115
+ await fse.writeFile(path.join(sessionDir, "conversation.jsonl"), jsonl, "utf-8");
116
+ await this.updateSessionIndex(metadata);
117
+ return sessionId;
118
+ }
119
+ /**
120
+ * Checks whether a session from `source` with `originalId` was already imported.
121
+ * Uses the session index for O(n) lookup with `importedFrom` field.
122
+ */
123
+ async isAlreadyImported(source, originalId) {
124
+ const indexPath = path.join(AUTOHAND_PATHS.sessions, "index.json");
125
+ if (!await fse.pathExists(indexPath)) {
126
+ return false;
127
+ }
128
+ try {
129
+ const loaded = await fse.readJson(indexPath);
130
+ if (!loaded || !Array.isArray(loaded.sessions)) return false;
131
+ return loaded.sessions.some(
132
+ (s) => s.importedFrom?.source === source && s.importedFrom?.originalId === originalId
133
+ );
134
+ } catch {
135
+ return false;
136
+ }
137
+ }
138
+ // ---------------------------------------------------------------
139
+ // Session index management
140
+ // ---------------------------------------------------------------
141
+ /**
142
+ * Adds a session entry to `~/.autohand/sessions/index.json`.
143
+ * Creates the file if it does not exist.
144
+ */
145
+ async updateSessionIndex(metadata) {
146
+ const indexPath = path.join(AUTOHAND_PATHS.sessions, "index.json");
147
+ let index = { sessions: [], byProject: {} };
148
+ if (await fse.pathExists(indexPath)) {
149
+ try {
150
+ const loaded = await fse.readJson(indexPath);
151
+ if (loaded && typeof loaded === "object" && Array.isArray(loaded.sessions) && loaded.byProject && typeof loaded.byProject === "object") {
152
+ index = loaded;
153
+ }
154
+ } catch {
155
+ }
156
+ }
157
+ const entry = {
158
+ id: metadata.sessionId,
159
+ projectPath: metadata.projectPath,
160
+ createdAt: metadata.createdAt,
161
+ summary: metadata.summary
162
+ };
163
+ if (metadata.importedFrom) {
164
+ entry.importedFrom = {
165
+ source: metadata.importedFrom.source,
166
+ originalId: metadata.importedFrom.originalId
167
+ };
168
+ }
169
+ index.sessions.push(entry);
170
+ if (!index.byProject[metadata.projectPath]) {
171
+ index.byProject[metadata.projectPath] = [];
172
+ }
173
+ index.byProject[metadata.projectPath].push(metadata.sessionId);
174
+ await fse.ensureDir(AUTOHAND_PATHS.sessions);
175
+ await fse.writeJson(indexPath, index, { spaces: 2 });
176
+ }
177
+ // ---------------------------------------------------------------
178
+ // Utility
179
+ // ---------------------------------------------------------------
180
+ /**
181
+ * Safely read and parse a JSON file with pre-validation.
182
+ * Returns the parsed data, or throws with a descriptive error message.
183
+ * Handles empty files, corrupted JSON, and non-object content gracefully.
184
+ */
185
+ async safeReadJson(filePath) {
186
+ const content = await fse.readFile(filePath, "utf-8");
187
+ if (!content.trim()) {
188
+ throw new Error(`File is empty: ${path.basename(filePath)}`);
189
+ }
190
+ try {
191
+ const parsed = JSON.parse(content);
192
+ return parsed;
193
+ } catch (err) {
194
+ throw new Error(
195
+ `Invalid JSON in ${path.basename(filePath)}: ${err instanceof Error ? err.message : String(err)}`
196
+ );
197
+ }
198
+ }
199
+ /**
200
+ * Simple promise-based delay.
201
+ */
202
+ delay(ms) {
203
+ return new Promise((resolve) => setTimeout(resolve, ms));
204
+ }
205
+ };
206
+
207
+ // src/import/importers/ClaudeImporter.ts
208
+ var ClaudeImporter = class extends BaseImporter {
209
+ constructor() {
210
+ super(...arguments);
211
+ this.name = "claude";
212
+ this.displayName = "Claude Code";
213
+ this.homePath = "~/.claude";
214
+ }
215
+ // ---------------------------------------------------------------
216
+ // scan()
217
+ // ---------------------------------------------------------------
218
+ async scan() {
219
+ const available = /* @__PURE__ */ new Map();
220
+ const home = this.resolvedHomePath;
221
+ if (!await fse2.pathExists(home)) {
222
+ return { source: this.name, available };
223
+ }
224
+ const projectsDir = path2.join(home, "projects");
225
+ let sessionCount = 0;
226
+ let memoryCount = 0;
227
+ if (await fse2.pathExists(projectsDir)) {
228
+ const entries = await fse2.readdir(projectsDir, { withFileTypes: true });
229
+ const projectDirs = entries.filter((e) => e.isDirectory());
230
+ for (const dir of projectDirs) {
231
+ const projectDir = path2.join(projectsDir, dir.name);
232
+ const projectEntries = await fse2.readdir(projectDir, { withFileTypes: true });
233
+ const jsonlFiles = projectEntries.filter((e) => e.isFile() && e.name.endsWith(".jsonl"));
234
+ sessionCount += jsonlFiles.length;
235
+ const hasMemoryDir = await fse2.pathExists(path2.join(projectDir, "memory"));
236
+ const hasClaudeMd = await fse2.pathExists(path2.join(projectDir, "CLAUDE.md"));
237
+ if (hasMemoryDir || hasClaudeMd) {
238
+ memoryCount++;
239
+ }
240
+ }
241
+ }
242
+ if (sessionCount > 0) {
243
+ available.set("sessions", {
244
+ count: sessionCount,
245
+ description: `${sessionCount} session file${sessionCount !== 1 ? "s" : ""} across project directories`
246
+ });
247
+ }
248
+ const settingsPath = path2.join(home, "settings.json");
249
+ if (await fse2.pathExists(settingsPath)) {
250
+ available.set("settings", { count: 1, description: "Claude Code settings.json" });
251
+ }
252
+ const skillsDir = path2.join(home, "skills");
253
+ if (await fse2.pathExists(skillsDir)) {
254
+ const skillEntries = await fse2.readdir(skillsDir, { withFileTypes: true });
255
+ const skillFiles = skillEntries.filter((e) => e.isFile());
256
+ if (skillFiles.length > 0) {
257
+ available.set("skills", {
258
+ count: skillFiles.length,
259
+ description: `${skillFiles.length} skill file${skillFiles.length !== 1 ? "s" : ""}`
260
+ });
261
+ }
262
+ }
263
+ if (memoryCount > 0) {
264
+ available.set("memory", {
265
+ count: memoryCount,
266
+ description: `${memoryCount} project${memoryCount !== 1 ? "s" : ""} with memory data`
267
+ });
268
+ }
269
+ return { source: this.name, available };
270
+ }
271
+ // ---------------------------------------------------------------
272
+ // import()
273
+ // ---------------------------------------------------------------
274
+ async import(categories, onProgress) {
275
+ const start = Date.now();
276
+ const imported = /* @__PURE__ */ new Map();
277
+ const errors = [];
278
+ for (const category of categories) {
279
+ switch (category) {
280
+ case "sessions":
281
+ await this.importSessions(imported, errors, onProgress);
282
+ break;
283
+ case "settings":
284
+ await this.importSettings(imported, errors, onProgress);
285
+ break;
286
+ case "skills":
287
+ await this.importSkills(imported, errors, onProgress);
288
+ break;
289
+ case "memory":
290
+ await this.importMemory(imported, errors, onProgress);
291
+ break;
292
+ default:
293
+ break;
294
+ }
295
+ }
296
+ return {
297
+ source: this.name,
298
+ imported,
299
+ errors,
300
+ duration: Date.now() - start
301
+ };
302
+ }
303
+ // ---------------------------------------------------------------
304
+ // Sessions
305
+ // ---------------------------------------------------------------
306
+ async importSessions(imported, errors, onProgress) {
307
+ const home = this.resolvedHomePath;
308
+ const projectsDir = path2.join(home, "projects");
309
+ let success = 0;
310
+ let failed = 0;
311
+ let skipped = 0;
312
+ const skipReasons = {};
313
+ const trackSkip = (reason) => {
314
+ skipped++;
315
+ skipReasons[reason] = (skipReasons[reason] ?? 0) + 1;
316
+ };
317
+ if (!await fse2.pathExists(projectsDir)) {
318
+ imported.set("sessions", { success: 0, failed: 0, skipped: 0 });
319
+ return;
320
+ }
321
+ const projectEntries = await fse2.readdir(projectsDir, { withFileTypes: true });
322
+ const projectDirs = projectEntries.filter((e) => e.isDirectory());
323
+ const allSessionFiles = [];
324
+ for (const dir of projectDirs) {
325
+ const projectDir = path2.join(projectsDir, dir.name);
326
+ const entries = await fse2.readdir(projectDir, { withFileTypes: true });
327
+ const jsonlFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl"));
328
+ for (const f of jsonlFiles) {
329
+ allSessionFiles.push({
330
+ filePath: path2.join(projectDir, f.name),
331
+ projectDirName: dir.name
332
+ });
333
+ }
334
+ }
335
+ const total = allSessionFiles.length;
336
+ for (let i = 0; i < allSessionFiles.length; i++) {
337
+ const { filePath, projectDirName } = allSessionFiles[i];
338
+ onProgress?.({
339
+ category: "sessions",
340
+ current: i + 1,
341
+ total,
342
+ item: path2.basename(filePath),
343
+ status: "importing"
344
+ });
345
+ try {
346
+ const fileContent = await fse2.readFile(filePath, "utf-8");
347
+ if (!fileContent.trim()) {
348
+ trackSkip("empty file");
349
+ continue;
350
+ }
351
+ const records = await this.readJsonlFile(filePath);
352
+ if (records.length === 0) {
353
+ trackSkip("no valid JSON records");
354
+ continue;
355
+ }
356
+ const events = records;
357
+ const relevantEvents = events.filter(
358
+ (e) => (e.type === "user" || e.type === "assistant") && !e.isMeta && e.message
359
+ );
360
+ if (relevantEvents.length === 0) {
361
+ trackSkip("no user/assistant messages");
362
+ continue;
363
+ }
364
+ const sessionGroups = /* @__PURE__ */ new Map();
365
+ for (const event of relevantEvents) {
366
+ const sid = event.sessionId ?? "unknown";
367
+ if (!sessionGroups.has(sid)) {
368
+ sessionGroups.set(sid, []);
369
+ }
370
+ sessionGroups.get(sid).push(event);
371
+ }
372
+ for (const [sessionId, sessionEvents] of sessionGroups) {
373
+ const messages = sessionEvents.map((e) => ({
374
+ role: e.message.role,
375
+ content: this.extractContent(e.message.content),
376
+ timestamp: e.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
377
+ }));
378
+ const firstEvent = sessionEvents[0];
379
+ const cwd = firstEvent.cwd ?? this.projectDirNameToPath(projectDirName);
380
+ const model = this.extractModel(sessionEvents) ?? "unknown";
381
+ const projectName = path2.basename(cwd);
382
+ const result = await this.writeAutohandSession({
383
+ projectPath: cwd,
384
+ projectName,
385
+ model,
386
+ messages,
387
+ source: this.name,
388
+ originalId: sessionId,
389
+ createdAt: messages[0].timestamp,
390
+ closedAt: messages[messages.length - 1].timestamp,
391
+ summary: this.buildSummary(messages),
392
+ status: "completed"
393
+ });
394
+ if (result === null) {
395
+ trackSkip("already imported");
396
+ } else {
397
+ success++;
398
+ }
399
+ }
400
+ } catch (err) {
401
+ failed++;
402
+ errors.push({
403
+ category: "sessions",
404
+ item: path2.basename(filePath),
405
+ error: err instanceof Error ? err.message : String(err),
406
+ retriable: true
407
+ });
408
+ }
409
+ }
410
+ imported.set("sessions", {
411
+ success,
412
+ failed,
413
+ skipped,
414
+ ...Object.keys(skipReasons).length > 0 ? { skipReasons } : {}
415
+ });
416
+ }
417
+ // ---------------------------------------------------------------
418
+ // Settings
419
+ // ---------------------------------------------------------------
420
+ async importSettings(imported, errors, onProgress) {
421
+ const settingsPath = path2.join(this.resolvedHomePath, "settings.json");
422
+ if (!await fse2.pathExists(settingsPath)) {
423
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
424
+ return;
425
+ }
426
+ onProgress?.({
427
+ category: "settings",
428
+ current: 1,
429
+ total: 1,
430
+ item: "settings.json",
431
+ status: "importing"
432
+ });
433
+ try {
434
+ const settings = await this.safeReadJson(settingsPath);
435
+ const permissions = settings.permissions;
436
+ if (permissions?.allow) {
437
+ const configDir = AUTOHAND_PATHS.config;
438
+ await fse2.ensureDir(configDir);
439
+ const importedSettingsPath = path2.join(configDir, "imported-claude-settings.json");
440
+ await fse2.writeJson(importedSettingsPath, {
441
+ importedFrom: "claude",
442
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
443
+ permissions: permissions.allow,
444
+ raw: settings
445
+ }, { spaces: 2 });
446
+ }
447
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
448
+ onProgress?.({
449
+ category: "settings",
450
+ current: 1,
451
+ total: 1,
452
+ item: "settings.json",
453
+ status: "done"
454
+ });
455
+ } catch (err) {
456
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
457
+ errors.push({
458
+ category: "settings",
459
+ item: "settings.json",
460
+ error: err instanceof Error ? err.message : String(err),
461
+ retriable: false
462
+ });
463
+ }
464
+ }
465
+ // ---------------------------------------------------------------
466
+ // Skills
467
+ // ---------------------------------------------------------------
468
+ async importSkills(imported, errors, onProgress) {
469
+ const skillsDir = path2.join(this.resolvedHomePath, "skills");
470
+ if (!await fse2.pathExists(skillsDir)) {
471
+ imported.set("skills", { success: 0, failed: 0, skipped: 1 });
472
+ return;
473
+ }
474
+ const entries = await fse2.readdir(skillsDir, { withFileTypes: true });
475
+ const skillFiles = entries.filter((e) => e.isFile());
476
+ let success = 0;
477
+ let failed = 0;
478
+ const total = skillFiles.length;
479
+ const destDir = path2.join(AUTOHAND_PATHS.skills, "imported-claude");
480
+ for (let i = 0; i < skillFiles.length; i++) {
481
+ const file = skillFiles[i];
482
+ const src = path2.join(skillsDir, file.name);
483
+ const dest = path2.join(destDir, file.name);
484
+ onProgress?.({
485
+ category: "skills",
486
+ current: i + 1,
487
+ total,
488
+ item: file.name,
489
+ status: "importing"
490
+ });
491
+ try {
492
+ await fse2.ensureDir(destDir);
493
+ await fse2.copy(src, dest);
494
+ success++;
495
+ } catch (err) {
496
+ failed++;
497
+ errors.push({
498
+ category: "skills",
499
+ item: file.name,
500
+ error: err instanceof Error ? err.message : String(err),
501
+ retriable: true
502
+ });
503
+ }
504
+ }
505
+ imported.set("skills", { success, failed, skipped: 0 });
506
+ }
507
+ // ---------------------------------------------------------------
508
+ // Memory
509
+ // ---------------------------------------------------------------
510
+ async importMemory(imported, errors, onProgress) {
511
+ const projectsDir = path2.join(this.resolvedHomePath, "projects");
512
+ let success = 0;
513
+ let failed = 0;
514
+ if (!await fse2.pathExists(projectsDir)) {
515
+ imported.set("memory", { success: 0, failed: 0, skipped: 0 });
516
+ return;
517
+ }
518
+ const entries = await fse2.readdir(projectsDir, { withFileTypes: true });
519
+ const projectDirs = entries.filter((e) => e.isDirectory());
520
+ const total = projectDirs.length;
521
+ for (let i = 0; i < projectDirs.length; i++) {
522
+ const dir = projectDirs[i];
523
+ const projectDir = path2.join(projectsDir, dir.name);
524
+ const hasMemoryDir = await fse2.pathExists(path2.join(projectDir, "memory"));
525
+ const hasClaudeMd = await fse2.pathExists(path2.join(projectDir, "CLAUDE.md"));
526
+ if (!hasMemoryDir && !hasClaudeMd) {
527
+ continue;
528
+ }
529
+ onProgress?.({
530
+ category: "memory",
531
+ current: i + 1,
532
+ total,
533
+ item: dir.name,
534
+ status: "importing"
535
+ });
536
+ try {
537
+ const projectHash = dir.name.replace(/[^a-zA-Z0-9-]/g, "_");
538
+ const destDir = path2.join(AUTOHAND_PATHS.projects, projectHash, "imported-claude");
539
+ await fse2.ensureDir(destDir);
540
+ if (hasMemoryDir) {
541
+ await fse2.copy(path2.join(projectDir, "memory"), path2.join(destDir, "memory"));
542
+ }
543
+ if (hasClaudeMd) {
544
+ await fse2.copy(path2.join(projectDir, "CLAUDE.md"), path2.join(destDir, "CLAUDE.md"));
545
+ }
546
+ success++;
547
+ } catch (err) {
548
+ failed++;
549
+ errors.push({
550
+ category: "memory",
551
+ item: dir.name,
552
+ error: err instanceof Error ? err.message : String(err),
553
+ retriable: true
554
+ });
555
+ }
556
+ }
557
+ imported.set("memory", { success, failed, skipped: 0 });
558
+ }
559
+ // ---------------------------------------------------------------
560
+ // Helpers
561
+ // ---------------------------------------------------------------
562
+ /**
563
+ * Extract text content from a Claude message content field.
564
+ * Content can be a string or an array of content blocks.
565
+ */
566
+ extractContent(content) {
567
+ if (typeof content === "string") {
568
+ return content;
569
+ }
570
+ if (Array.isArray(content)) {
571
+ return content.filter((block) => block.type === "text" && block.text).map((block) => block.text).join("");
572
+ }
573
+ return "";
574
+ }
575
+ /**
576
+ * Extract the model name from session events. Takes the first found model.
577
+ */
578
+ extractModel(events) {
579
+ for (const event of events) {
580
+ if (event.message?.model) {
581
+ return event.message.model;
582
+ }
583
+ }
584
+ return void 0;
585
+ }
586
+ /**
587
+ * Convert a project directory name (e.g. "-Users-me-project") to a path.
588
+ */
589
+ projectDirNameToPath(dirName) {
590
+ return "/" + dirName.replace(/^-/, "").replace(/-/g, "/");
591
+ }
592
+ /**
593
+ * Build a brief summary from the first real user message.
594
+ * Skips system-injected context (XML tags, CLAUDE.md, etc.)
595
+ */
596
+ buildSummary(messages) {
597
+ for (const msg of messages) {
598
+ if (msg.role !== "user") continue;
599
+ const cleaned = this.stripSystemContent(msg.content);
600
+ if (cleaned.length > 0) {
601
+ const text = cleaned.slice(0, 100);
602
+ return text.length < cleaned.length ? `${text}...` : text;
603
+ }
604
+ }
605
+ return "Imported Claude session";
606
+ }
607
+ /**
608
+ * Strip system-injected XML tags and their content from a message,
609
+ * returning only the actual user text.
610
+ */
611
+ stripSystemContent(text) {
612
+ let cleaned = text;
613
+ const systemTags = [
614
+ "local-command-caveat",
615
+ "system-reminder",
616
+ "user_instructions",
617
+ "environment_context",
618
+ "context",
619
+ "automatic_reminders",
620
+ "user_request",
621
+ "bash-input",
622
+ "bash-stdout",
623
+ "bash-stderr"
624
+ ];
625
+ for (const tag of systemTags) {
626
+ const pattern = new RegExp(`<${tag}>[\\s\\S]*?</${tag}>`, "g");
627
+ cleaned = cleaned.replace(pattern, "");
628
+ }
629
+ return cleaned.trim();
630
+ }
631
+ };
632
+
633
+ // src/import/importers/CodexImporter.ts
634
+ import path3 from "path";
635
+ import fse3 from "fs-extra";
636
+ var CodexImporter = class extends BaseImporter {
637
+ constructor() {
638
+ super(...arguments);
639
+ this.name = "codex";
640
+ this.displayName = "OpenAI Codex";
641
+ this.homePath = "~/.codex";
642
+ }
643
+ // ---------------------------------------------------------------
644
+ // scan()
645
+ // ---------------------------------------------------------------
646
+ async scan() {
647
+ const available = /* @__PURE__ */ new Map();
648
+ const home = this.resolvedHomePath;
649
+ if (!await fse3.pathExists(home)) {
650
+ return { source: this.name, available };
651
+ }
652
+ const sessionsDir = path3.join(home, "sessions");
653
+ if (await fse3.pathExists(sessionsDir)) {
654
+ const sessionFiles = await this.walkJsonlFiles(sessionsDir);
655
+ if (sessionFiles.length > 0) {
656
+ available.set("sessions", {
657
+ count: sessionFiles.length,
658
+ description: `${sessionFiles.length} session file${sessionFiles.length !== 1 ? "s" : ""}`
659
+ });
660
+ }
661
+ }
662
+ if (await fse3.pathExists(path3.join(home, "config.toml"))) {
663
+ available.set("settings", { count: 1, description: "Codex config.toml" });
664
+ }
665
+ const skillsDir = path3.join(home, "skills");
666
+ if (await fse3.pathExists(skillsDir)) {
667
+ const skillEntries = await fse3.readdir(skillsDir, { withFileTypes: true });
668
+ const skillFiles = skillEntries.filter((e) => e.isFile());
669
+ if (skillFiles.length > 0) {
670
+ available.set("skills", {
671
+ count: skillFiles.length,
672
+ description: `${skillFiles.length} skill file${skillFiles.length !== 1 ? "s" : ""}`
673
+ });
674
+ }
675
+ }
676
+ const rulesDir = path3.join(home, "rules");
677
+ if (await fse3.pathExists(rulesDir)) {
678
+ const ruleEntries = await fse3.readdir(rulesDir, { withFileTypes: true });
679
+ const ruleFiles = ruleEntries.filter((e) => e.isFile());
680
+ if (ruleFiles.length > 0) {
681
+ available.set("memory", {
682
+ count: ruleFiles.length,
683
+ description: `${ruleFiles.length} rule file${ruleFiles.length !== 1 ? "s" : ""}`
684
+ });
685
+ }
686
+ }
687
+ return { source: this.name, available };
688
+ }
689
+ // ---------------------------------------------------------------
690
+ // import()
691
+ // ---------------------------------------------------------------
692
+ async import(categories, onProgress) {
693
+ const start = Date.now();
694
+ const imported = /* @__PURE__ */ new Map();
695
+ const errors = [];
696
+ for (const category of categories) {
697
+ switch (category) {
698
+ case "sessions":
699
+ await this.importSessions(imported, errors, onProgress);
700
+ break;
701
+ case "settings":
702
+ await this.importSettings(imported, errors, onProgress);
703
+ break;
704
+ case "skills":
705
+ await this.importSkills(imported, errors, onProgress);
706
+ break;
707
+ default:
708
+ break;
709
+ }
710
+ }
711
+ return {
712
+ source: this.name,
713
+ imported,
714
+ errors,
715
+ duration: Date.now() - start
716
+ };
717
+ }
718
+ // ---------------------------------------------------------------
719
+ // Sessions
720
+ // ---------------------------------------------------------------
721
+ async importSessions(imported, errors, onProgress) {
722
+ const sessionsDir = path3.join(this.resolvedHomePath, "sessions");
723
+ let success = 0;
724
+ let failed = 0;
725
+ let skipped = 0;
726
+ const skipReasons = {};
727
+ const trackSkip = (reason) => {
728
+ skipped++;
729
+ skipReasons[reason] = (skipReasons[reason] ?? 0) + 1;
730
+ };
731
+ if (!await fse3.pathExists(sessionsDir)) {
732
+ imported.set("sessions", { success: 0, failed: 0, skipped: 0 });
733
+ return;
734
+ }
735
+ const sessionFiles = await this.walkJsonlFiles(sessionsDir);
736
+ const total = sessionFiles.length;
737
+ for (let i = 0; i < sessionFiles.length; i++) {
738
+ const filePath = sessionFiles[i];
739
+ onProgress?.({
740
+ category: "sessions",
741
+ current: i + 1,
742
+ total,
743
+ item: path3.basename(filePath),
744
+ status: "importing"
745
+ });
746
+ try {
747
+ const fileContent = await fse3.readFile(filePath, "utf-8");
748
+ if (!fileContent.trim()) {
749
+ trackSkip("empty file");
750
+ continue;
751
+ }
752
+ const records = await this.readJsonlFile(filePath);
753
+ if (records.length === 0) {
754
+ trackSkip("no valid JSON records");
755
+ continue;
756
+ }
757
+ const events = records;
758
+ const metaEvent = events.find((e) => e.type === "session_meta");
759
+ const sessionId = metaEvent?.payload?.id ?? path3.basename(filePath, ".jsonl");
760
+ const cwd = metaEvent?.payload?.cwd ?? "/unknown";
761
+ const messages = [];
762
+ for (const event of events) {
763
+ if (event.type === "response_item") {
764
+ const payload = event.payload;
765
+ if (payload.type === "message" && payload.role && payload.content) {
766
+ const text = payload.content.filter((c) => (c.type === "input_text" || c.type === "output_text") && c.text).map((c) => c.text).join("");
767
+ if (text && !this.isSystemMessage(text)) {
768
+ messages.push({
769
+ role: payload.role,
770
+ content: text,
771
+ timestamp: event.timestamp
772
+ });
773
+ }
774
+ }
775
+ } else if (event.type === "event_msg") {
776
+ const payload = event.payload;
777
+ if (payload.type === "agent_message" && payload.message) {
778
+ messages.push({
779
+ role: "assistant",
780
+ content: payload.message,
781
+ timestamp: event.timestamp
782
+ });
783
+ }
784
+ }
785
+ }
786
+ if (messages.length === 0) {
787
+ trackSkip("no user messages (only system content)");
788
+ continue;
789
+ }
790
+ const projectName = path3.basename(cwd);
791
+ const result = await this.writeAutohandSession({
792
+ projectPath: cwd,
793
+ projectName,
794
+ model: "codex",
795
+ messages,
796
+ source: this.name,
797
+ originalId: sessionId,
798
+ createdAt: messages[0].timestamp,
799
+ closedAt: messages[messages.length - 1].timestamp,
800
+ summary: this.buildSummary(messages),
801
+ status: "completed"
802
+ });
803
+ if (result === null) {
804
+ trackSkip("already imported");
805
+ } else {
806
+ success++;
807
+ }
808
+ } catch (err) {
809
+ failed++;
810
+ errors.push({
811
+ category: "sessions",
812
+ item: path3.basename(filePath),
813
+ error: err instanceof Error ? err.message : String(err),
814
+ retriable: true
815
+ });
816
+ }
817
+ }
818
+ imported.set("sessions", {
819
+ success,
820
+ failed,
821
+ skipped,
822
+ ...Object.keys(skipReasons).length > 0 ? { skipReasons } : {}
823
+ });
824
+ }
825
+ // ---------------------------------------------------------------
826
+ // Settings (TOML)
827
+ // ---------------------------------------------------------------
828
+ async importSettings(imported, errors, onProgress) {
829
+ const configPath = path3.join(this.resolvedHomePath, "config.toml");
830
+ if (!await fse3.pathExists(configPath)) {
831
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
832
+ return;
833
+ }
834
+ onProgress?.({
835
+ category: "settings",
836
+ current: 1,
837
+ total: 1,
838
+ item: "config.toml",
839
+ status: "importing"
840
+ });
841
+ try {
842
+ const tomlContent = await fse3.readFile(configPath, "utf-8");
843
+ const parsed = this.parseToml(tomlContent);
844
+ const configDir = AUTOHAND_PATHS.config;
845
+ await fse3.ensureDir(configDir);
846
+ await fse3.writeJson(
847
+ path3.join(configDir, "imported-codex-settings.json"),
848
+ {
849
+ importedFrom: "codex",
850
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
851
+ parsed,
852
+ raw: tomlContent
853
+ },
854
+ { spaces: 2 }
855
+ );
856
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
857
+ onProgress?.({
858
+ category: "settings",
859
+ current: 1,
860
+ total: 1,
861
+ item: "config.toml",
862
+ status: "done"
863
+ });
864
+ } catch (err) {
865
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
866
+ errors.push({
867
+ category: "settings",
868
+ item: "config.toml",
869
+ error: err instanceof Error ? err.message : String(err),
870
+ retriable: false
871
+ });
872
+ }
873
+ }
874
+ // ---------------------------------------------------------------
875
+ // Skills
876
+ // ---------------------------------------------------------------
877
+ async importSkills(imported, errors, onProgress) {
878
+ const skillsDir = path3.join(this.resolvedHomePath, "skills");
879
+ if (!await fse3.pathExists(skillsDir)) {
880
+ imported.set("skills", { success: 0, failed: 0, skipped: 1 });
881
+ return;
882
+ }
883
+ const entries = await fse3.readdir(skillsDir, { withFileTypes: true });
884
+ const skillFiles = entries.filter((e) => e.isFile());
885
+ let success = 0;
886
+ let failed = 0;
887
+ const total = skillFiles.length;
888
+ const destDir = path3.join(AUTOHAND_PATHS.skills, "imported-codex");
889
+ for (let i = 0; i < skillFiles.length; i++) {
890
+ const file = skillFiles[i];
891
+ const src = path3.join(skillsDir, file.name);
892
+ const dest = path3.join(destDir, file.name);
893
+ onProgress?.({
894
+ category: "skills",
895
+ current: i + 1,
896
+ total,
897
+ item: file.name,
898
+ status: "importing"
899
+ });
900
+ try {
901
+ await fse3.ensureDir(destDir);
902
+ await fse3.copy(src, dest);
903
+ success++;
904
+ } catch (err) {
905
+ failed++;
906
+ errors.push({
907
+ category: "skills",
908
+ item: file.name,
909
+ error: err instanceof Error ? err.message : String(err),
910
+ retriable: true
911
+ });
912
+ }
913
+ }
914
+ imported.set("skills", { success, failed, skipped: 0 });
915
+ }
916
+ // ---------------------------------------------------------------
917
+ // Helpers
918
+ // ---------------------------------------------------------------
919
+ /**
920
+ * Recursively walk a directory tree and collect all .jsonl file paths.
921
+ */
922
+ async walkJsonlFiles(dir) {
923
+ const results = [];
924
+ const entries = await fse3.readdir(dir, { withFileTypes: true });
925
+ for (const entry of entries) {
926
+ const fullPath = path3.join(dir, entry.name);
927
+ if (entry.isDirectory()) {
928
+ const nested = await this.walkJsonlFiles(fullPath);
929
+ results.push(...nested);
930
+ } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
931
+ results.push(fullPath);
932
+ }
933
+ }
934
+ return results;
935
+ }
936
+ /**
937
+ * Simple TOML parser. Handles:
938
+ * - `key = "value"` (quoted strings)
939
+ * - `key = value` (unquoted – numbers, booleans, bare strings)
940
+ * - `[section]` and `[section.subsection]` headers
941
+ * - `# comments`
942
+ * - blank lines
943
+ *
944
+ * Returns a flat object with dotted keys for sections
945
+ * (e.g. `{ "section.key": "value" }`).
946
+ */
947
+ parseToml(content) {
948
+ const result = {};
949
+ let currentSection = "";
950
+ for (const rawLine of content.split("\n")) {
951
+ const line = rawLine.trim();
952
+ if (!line || line.startsWith("#")) continue;
953
+ const sectionMatch = line.match(/^\[([^\]]+)\]$/);
954
+ if (sectionMatch) {
955
+ currentSection = sectionMatch[1];
956
+ continue;
957
+ }
958
+ const kvMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)\s*=\s*(.+)$/);
959
+ if (!kvMatch) continue;
960
+ const key = currentSection ? `${currentSection}.${kvMatch[1]}` : kvMatch[1];
961
+ let value = kvMatch[2].trim();
962
+ const inlineComment = value.indexOf(" #");
963
+ if (inlineComment > 0) {
964
+ value = value.slice(0, inlineComment).trim();
965
+ }
966
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
967
+ result[key] = value.slice(1, -1);
968
+ } else if (value === "true") {
969
+ result[key] = true;
970
+ } else if (value === "false") {
971
+ result[key] = false;
972
+ } else if (/^-?\d+(\.\d+)?$/.test(value)) {
973
+ result[key] = Number(value);
974
+ } else {
975
+ result[key] = value;
976
+ }
977
+ }
978
+ return result;
979
+ }
980
+ /**
981
+ * Detect system-injected context messages that should not be imported.
982
+ * These are Codex CLI-generated system prompts, environment info, etc.
983
+ */
984
+ isSystemMessage(text) {
985
+ const trimmed = text.trimStart();
986
+ return trimmed.startsWith("<user_instructions>") || trimmed.startsWith("<environment_context>") || trimmed.startsWith("<user_request>") || trimmed.startsWith("<automatic_reminders>") || trimmed.startsWith("<system-reminder>") || trimmed.startsWith("<context>") || trimmed.startsWith("# Agents Guidance\n");
987
+ }
988
+ /**
989
+ * Build a brief summary from the first real user message.
990
+ */
991
+ buildSummary(messages) {
992
+ const firstUser = messages.find((m) => m.role === "user");
993
+ if (!firstUser) return "Imported Codex session";
994
+ const text = firstUser.content.trim().slice(0, 100);
995
+ return text.length < firstUser.content.trim().length ? `${text}...` : text;
996
+ }
997
+ };
998
+
999
+ // src/import/importers/GeminiImporter.ts
1000
+ import path4 from "path";
1001
+ import fse4 from "fs-extra";
1002
+ var GeminiImporter = class extends BaseImporter {
1003
+ constructor() {
1004
+ super(...arguments);
1005
+ this.name = "gemini";
1006
+ this.displayName = "Google Gemini";
1007
+ this.homePath = "~/.gemini";
1008
+ }
1009
+ // ---------------------------------------------------------------
1010
+ // scan()
1011
+ // ---------------------------------------------------------------
1012
+ async scan() {
1013
+ const available = /* @__PURE__ */ new Map();
1014
+ const home = this.resolvedHomePath;
1015
+ if (!await fse4.pathExists(home)) {
1016
+ return { source: this.name, available };
1017
+ }
1018
+ const settingsPath = path4.join(home, "settings.json");
1019
+ const hasSettings = await fse4.pathExists(settingsPath);
1020
+ if (hasSettings) {
1021
+ available.set("settings", { count: 1, description: "Gemini settings.json" });
1022
+ try {
1023
+ const settings = await this.safeReadJson(settingsPath);
1024
+ const hooks = settings.hooks;
1025
+ if (hooks) {
1026
+ const hookSections = Object.keys(hooks).filter(
1027
+ (k) => Array.isArray(hooks[k]) && hooks[k].length > 0
1028
+ );
1029
+ if (hookSections.length > 0) {
1030
+ available.set("hooks", {
1031
+ count: hookSections.length,
1032
+ description: `${hookSections.length} hook section${hookSections.length !== 1 ? "s" : ""} (${hookSections.join(", ")})`
1033
+ });
1034
+ }
1035
+ }
1036
+ } catch {
1037
+ }
1038
+ }
1039
+ const geminiMdPath = path4.join(home, "GEMINI.md");
1040
+ if (await fse4.pathExists(geminiMdPath)) {
1041
+ available.set("memory", { count: 1, description: "GEMINI.md project memory" });
1042
+ }
1043
+ return { source: this.name, available };
1044
+ }
1045
+ // ---------------------------------------------------------------
1046
+ // import()
1047
+ // ---------------------------------------------------------------
1048
+ async import(categories, onProgress) {
1049
+ const start = Date.now();
1050
+ const imported = /* @__PURE__ */ new Map();
1051
+ const errors = [];
1052
+ for (const category of categories) {
1053
+ switch (category) {
1054
+ case "settings":
1055
+ await this.importSettings(imported, errors, onProgress);
1056
+ break;
1057
+ case "hooks":
1058
+ await this.importHooks(imported, errors, onProgress);
1059
+ break;
1060
+ case "memory":
1061
+ await this.importMemory(imported, errors, onProgress);
1062
+ break;
1063
+ default:
1064
+ break;
1065
+ }
1066
+ }
1067
+ return {
1068
+ source: this.name,
1069
+ imported,
1070
+ errors,
1071
+ duration: Date.now() - start
1072
+ };
1073
+ }
1074
+ // ---------------------------------------------------------------
1075
+ // Settings
1076
+ // ---------------------------------------------------------------
1077
+ async importSettings(imported, errors, onProgress) {
1078
+ const settingsPath = path4.join(this.resolvedHomePath, "settings.json");
1079
+ if (!await fse4.pathExists(settingsPath)) {
1080
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
1081
+ return;
1082
+ }
1083
+ onProgress?.({
1084
+ category: "settings",
1085
+ current: 1,
1086
+ total: 1,
1087
+ item: "settings.json",
1088
+ status: "importing"
1089
+ });
1090
+ try {
1091
+ const settings = await this.safeReadJson(settingsPath);
1092
+ const configDir = AUTOHAND_PATHS.config;
1093
+ await fse4.ensureDir(configDir);
1094
+ await fse4.writeJson(
1095
+ path4.join(configDir, "imported-gemini-settings.json"),
1096
+ {
1097
+ importedFrom: "gemini",
1098
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1099
+ raw: settings
1100
+ },
1101
+ { spaces: 2 }
1102
+ );
1103
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
1104
+ onProgress?.({
1105
+ category: "settings",
1106
+ current: 1,
1107
+ total: 1,
1108
+ item: "settings.json",
1109
+ status: "done"
1110
+ });
1111
+ } catch (err) {
1112
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
1113
+ errors.push({
1114
+ category: "settings",
1115
+ item: "settings.json",
1116
+ error: err instanceof Error ? err.message : String(err),
1117
+ retriable: false
1118
+ });
1119
+ }
1120
+ }
1121
+ // ---------------------------------------------------------------
1122
+ // Hooks
1123
+ // ---------------------------------------------------------------
1124
+ async importHooks(imported, errors, onProgress) {
1125
+ const settingsPath = path4.join(this.resolvedHomePath, "settings.json");
1126
+ if (!await fse4.pathExists(settingsPath)) {
1127
+ imported.set("hooks", { success: 0, failed: 0, skipped: 1 });
1128
+ return;
1129
+ }
1130
+ onProgress?.({
1131
+ category: "hooks",
1132
+ current: 1,
1133
+ total: 1,
1134
+ item: "hooks from settings.json",
1135
+ status: "importing"
1136
+ });
1137
+ try {
1138
+ const settings = await this.safeReadJson(settingsPath);
1139
+ const hooks = settings.hooks;
1140
+ if (!hooks || Object.keys(hooks).length === 0) {
1141
+ imported.set("hooks", { success: 0, failed: 0, skipped: 1 });
1142
+ return;
1143
+ }
1144
+ const configDir = AUTOHAND_PATHS.config;
1145
+ await fse4.ensureDir(configDir);
1146
+ await fse4.writeJson(
1147
+ path4.join(configDir, "imported-gemini-hooks.json"),
1148
+ {
1149
+ importedFrom: "gemini",
1150
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1151
+ hooks
1152
+ },
1153
+ { spaces: 2 }
1154
+ );
1155
+ imported.set("hooks", { success: 1, failed: 0, skipped: 0 });
1156
+ onProgress?.({
1157
+ category: "hooks",
1158
+ current: 1,
1159
+ total: 1,
1160
+ item: "hooks from settings.json",
1161
+ status: "done"
1162
+ });
1163
+ } catch (err) {
1164
+ imported.set("hooks", { success: 0, failed: 1, skipped: 0 });
1165
+ errors.push({
1166
+ category: "hooks",
1167
+ item: "hooks from settings.json",
1168
+ error: err instanceof Error ? err.message : String(err),
1169
+ retriable: false
1170
+ });
1171
+ }
1172
+ }
1173
+ // ---------------------------------------------------------------
1174
+ // Memory
1175
+ // ---------------------------------------------------------------
1176
+ async importMemory(imported, errors, onProgress) {
1177
+ const geminiMdPath = path4.join(this.resolvedHomePath, "GEMINI.md");
1178
+ if (!await fse4.pathExists(geminiMdPath)) {
1179
+ imported.set("memory", { success: 0, failed: 0, skipped: 1 });
1180
+ return;
1181
+ }
1182
+ onProgress?.({
1183
+ category: "memory",
1184
+ current: 1,
1185
+ total: 1,
1186
+ item: "GEMINI.md",
1187
+ status: "importing"
1188
+ });
1189
+ try {
1190
+ const destDir = path4.join(AUTOHAND_PATHS.memory, "imported-gemini");
1191
+ await fse4.ensureDir(destDir);
1192
+ await fse4.copy(geminiMdPath, path4.join(destDir, "GEMINI.md"));
1193
+ imported.set("memory", { success: 1, failed: 0, skipped: 0 });
1194
+ onProgress?.({
1195
+ category: "memory",
1196
+ current: 1,
1197
+ total: 1,
1198
+ item: "GEMINI.md",
1199
+ status: "done"
1200
+ });
1201
+ } catch (err) {
1202
+ imported.set("memory", { success: 0, failed: 1, skipped: 0 });
1203
+ errors.push({
1204
+ category: "memory",
1205
+ item: "GEMINI.md",
1206
+ error: err instanceof Error ? err.message : String(err),
1207
+ retriable: true
1208
+ });
1209
+ }
1210
+ }
1211
+ };
1212
+
1213
+ // src/import/importers/CursorImporter.ts
1214
+ import path5 from "path";
1215
+ import fse5 from "fs-extra";
1216
+ var CursorImporter = class extends BaseImporter {
1217
+ constructor() {
1218
+ super(...arguments);
1219
+ this.name = "cursor";
1220
+ this.displayName = "Cursor";
1221
+ this.homePath = "~/.cursor";
1222
+ }
1223
+ // ---------------------------------------------------------------
1224
+ // scan()
1225
+ // ---------------------------------------------------------------
1226
+ async scan() {
1227
+ const available = /* @__PURE__ */ new Map();
1228
+ const home = this.resolvedHomePath;
1229
+ if (!await fse5.pathExists(home)) {
1230
+ return { source: this.name, available };
1231
+ }
1232
+ const hooksPath = path5.join(home, "hooks.json");
1233
+ if (await fse5.pathExists(hooksPath)) {
1234
+ available.set("settings", { count: 1, description: "Cursor hooks.json preferences" });
1235
+ available.set("hooks", { count: 1, description: "Cursor hook configurations" });
1236
+ }
1237
+ const mcpPath = path5.join(home, "mcp.json");
1238
+ if (await fse5.pathExists(mcpPath)) {
1239
+ available.set("mcp", { count: 1, description: "Cursor MCP server configurations" });
1240
+ }
1241
+ return { source: this.name, available };
1242
+ }
1243
+ // ---------------------------------------------------------------
1244
+ // import()
1245
+ // ---------------------------------------------------------------
1246
+ async import(categories, onProgress) {
1247
+ const start = Date.now();
1248
+ const imported = /* @__PURE__ */ new Map();
1249
+ const errors = [];
1250
+ for (const category of categories) {
1251
+ switch (category) {
1252
+ case "settings":
1253
+ await this.importSettings(imported, errors, onProgress);
1254
+ break;
1255
+ case "hooks":
1256
+ await this.importHooks(imported, errors, onProgress);
1257
+ break;
1258
+ case "mcp":
1259
+ await this.importMcp(imported, errors, onProgress);
1260
+ break;
1261
+ default:
1262
+ break;
1263
+ }
1264
+ }
1265
+ return {
1266
+ source: this.name,
1267
+ imported,
1268
+ errors,
1269
+ duration: Date.now() - start
1270
+ };
1271
+ }
1272
+ // ---------------------------------------------------------------
1273
+ // Settings
1274
+ // ---------------------------------------------------------------
1275
+ async importSettings(imported, errors, onProgress) {
1276
+ const hooksPath = path5.join(this.resolvedHomePath, "hooks.json");
1277
+ if (!await fse5.pathExists(hooksPath)) {
1278
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
1279
+ return;
1280
+ }
1281
+ onProgress?.({
1282
+ category: "settings",
1283
+ current: 1,
1284
+ total: 1,
1285
+ item: "hooks.json",
1286
+ status: "importing"
1287
+ });
1288
+ try {
1289
+ const hooksData = await this.safeReadJson(hooksPath);
1290
+ const configDir = AUTOHAND_PATHS.config;
1291
+ await fse5.ensureDir(configDir);
1292
+ await fse5.writeJson(
1293
+ path5.join(configDir, "imported-cursor-settings.json"),
1294
+ {
1295
+ importedFrom: "cursor",
1296
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1297
+ raw: hooksData
1298
+ },
1299
+ { spaces: 2 }
1300
+ );
1301
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
1302
+ onProgress?.({
1303
+ category: "settings",
1304
+ current: 1,
1305
+ total: 1,
1306
+ item: "hooks.json",
1307
+ status: "done"
1308
+ });
1309
+ } catch (err) {
1310
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
1311
+ errors.push({
1312
+ category: "settings",
1313
+ item: "hooks.json",
1314
+ error: err instanceof Error ? err.message : String(err),
1315
+ retriable: false
1316
+ });
1317
+ }
1318
+ }
1319
+ // ---------------------------------------------------------------
1320
+ // Hooks
1321
+ // ---------------------------------------------------------------
1322
+ async importHooks(imported, errors, onProgress) {
1323
+ const hooksPath = path5.join(this.resolvedHomePath, "hooks.json");
1324
+ if (!await fse5.pathExists(hooksPath)) {
1325
+ imported.set("hooks", { success: 0, failed: 0, skipped: 1 });
1326
+ return;
1327
+ }
1328
+ onProgress?.({
1329
+ category: "hooks",
1330
+ current: 1,
1331
+ total: 1,
1332
+ item: "hooks.json",
1333
+ status: "importing"
1334
+ });
1335
+ try {
1336
+ const hooksData = await this.safeReadJson(hooksPath);
1337
+ const configDir = AUTOHAND_PATHS.config;
1338
+ await fse5.ensureDir(configDir);
1339
+ await fse5.writeJson(
1340
+ path5.join(configDir, "imported-cursor-hooks.json"),
1341
+ {
1342
+ importedFrom: "cursor",
1343
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1344
+ hooks: hooksData.hooks ?? hooksData
1345
+ },
1346
+ { spaces: 2 }
1347
+ );
1348
+ imported.set("hooks", { success: 1, failed: 0, skipped: 0 });
1349
+ onProgress?.({
1350
+ category: "hooks",
1351
+ current: 1,
1352
+ total: 1,
1353
+ item: "hooks.json",
1354
+ status: "done"
1355
+ });
1356
+ } catch (err) {
1357
+ imported.set("hooks", { success: 0, failed: 1, skipped: 0 });
1358
+ errors.push({
1359
+ category: "hooks",
1360
+ item: "hooks.json",
1361
+ error: err instanceof Error ? err.message : String(err),
1362
+ retriable: false
1363
+ });
1364
+ }
1365
+ }
1366
+ // ---------------------------------------------------------------
1367
+ // MCP
1368
+ // ---------------------------------------------------------------
1369
+ async importMcp(imported, errors, onProgress) {
1370
+ const mcpPath = path5.join(this.resolvedHomePath, "mcp.json");
1371
+ if (!await fse5.pathExists(mcpPath)) {
1372
+ imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
1373
+ return;
1374
+ }
1375
+ onProgress?.({
1376
+ category: "mcp",
1377
+ current: 1,
1378
+ total: 1,
1379
+ item: "mcp.json",
1380
+ status: "importing"
1381
+ });
1382
+ try {
1383
+ const mcpData = await this.safeReadJson(mcpPath);
1384
+ const configDir = AUTOHAND_PATHS.config;
1385
+ await fse5.ensureDir(configDir);
1386
+ await fse5.writeJson(
1387
+ path5.join(configDir, "imported-cursor-mcp.json"),
1388
+ {
1389
+ importedFrom: "cursor",
1390
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1391
+ mcpServers: mcpData.mcpServers ?? mcpData
1392
+ },
1393
+ { spaces: 2 }
1394
+ );
1395
+ imported.set("mcp", { success: 1, failed: 0, skipped: 0 });
1396
+ onProgress?.({
1397
+ category: "mcp",
1398
+ current: 1,
1399
+ total: 1,
1400
+ item: "mcp.json",
1401
+ status: "done"
1402
+ });
1403
+ } catch (err) {
1404
+ imported.set("mcp", { success: 0, failed: 1, skipped: 0 });
1405
+ errors.push({
1406
+ category: "mcp",
1407
+ item: "mcp.json",
1408
+ error: err instanceof Error ? err.message : String(err),
1409
+ retriable: false
1410
+ });
1411
+ }
1412
+ }
1413
+ };
1414
+
1415
+ // src/import/importers/ClineImporter.ts
1416
+ import path6 from "path";
1417
+ import fse6 from "fs-extra";
1418
+ var ClineImporter = class extends BaseImporter {
1419
+ constructor() {
1420
+ super(...arguments);
1421
+ this.name = "cline";
1422
+ this.displayName = "Cline";
1423
+ this.homePath = "~/.cline";
1424
+ }
1425
+ // ---------------------------------------------------------------
1426
+ // scan()
1427
+ // ---------------------------------------------------------------
1428
+ async scan() {
1429
+ const available = /* @__PURE__ */ new Map();
1430
+ const home = this.resolvedHomePath;
1431
+ if (!await fse6.pathExists(home)) {
1432
+ return { source: this.name, available };
1433
+ }
1434
+ const globalStatePath = path6.join(home, "data", "globalState.json");
1435
+ if (await fse6.pathExists(globalStatePath)) {
1436
+ available.set("settings", {
1437
+ count: 1,
1438
+ description: "Cline global state (model preferences, auto-approval, browser settings)"
1439
+ });
1440
+ }
1441
+ return { source: this.name, available };
1442
+ }
1443
+ // ---------------------------------------------------------------
1444
+ // import()
1445
+ // ---------------------------------------------------------------
1446
+ async import(categories, onProgress) {
1447
+ const start = Date.now();
1448
+ const imported = /* @__PURE__ */ new Map();
1449
+ const errors = [];
1450
+ for (const category of categories) {
1451
+ switch (category) {
1452
+ case "settings":
1453
+ await this.importSettings(imported, errors, onProgress);
1454
+ break;
1455
+ default:
1456
+ break;
1457
+ }
1458
+ }
1459
+ return {
1460
+ source: this.name,
1461
+ imported,
1462
+ errors,
1463
+ duration: Date.now() - start
1464
+ };
1465
+ }
1466
+ // ---------------------------------------------------------------
1467
+ // Settings
1468
+ // ---------------------------------------------------------------
1469
+ async importSettings(imported, errors, onProgress) {
1470
+ const globalStatePath = path6.join(this.resolvedHomePath, "data", "globalState.json");
1471
+ if (!await fse6.pathExists(globalStatePath)) {
1472
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
1473
+ return;
1474
+ }
1475
+ onProgress?.({
1476
+ category: "settings",
1477
+ current: 1,
1478
+ total: 1,
1479
+ item: "globalState.json",
1480
+ status: "importing"
1481
+ });
1482
+ try {
1483
+ const state = await this.safeReadJson(globalStatePath);
1484
+ const extracted = {};
1485
+ if (state.apiModelId) extracted.model = state.apiModelId;
1486
+ if (state.autoApprovalSettings) extracted.autoApproval = state.autoApprovalSettings;
1487
+ if (state.browserSettings) extracted.browser = state.browserSettings;
1488
+ if (state.workspaceRoots) extracted.workspaceRoots = state.workspaceRoots;
1489
+ const configDir = AUTOHAND_PATHS.config;
1490
+ await fse6.ensureDir(configDir);
1491
+ await fse6.writeJson(
1492
+ path6.join(configDir, "imported-cline-settings.json"),
1493
+ {
1494
+ importedFrom: "cline",
1495
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1496
+ ...extracted,
1497
+ raw: state
1498
+ },
1499
+ { spaces: 2 }
1500
+ );
1501
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
1502
+ onProgress?.({
1503
+ category: "settings",
1504
+ current: 1,
1505
+ total: 1,
1506
+ item: "globalState.json",
1507
+ status: "done"
1508
+ });
1509
+ } catch (err) {
1510
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
1511
+ errors.push({
1512
+ category: "settings",
1513
+ item: "globalState.json",
1514
+ error: err instanceof Error ? err.message : String(err),
1515
+ retriable: false
1516
+ });
1517
+ }
1518
+ }
1519
+ };
1520
+
1521
+ // src/import/importers/ContinueImporter.ts
1522
+ import path7 from "path";
1523
+ import fse7 from "fs-extra";
1524
+ var ContinueImporter = class extends BaseImporter {
1525
+ constructor() {
1526
+ super(...arguments);
1527
+ this.name = "continue";
1528
+ this.displayName = "Continue.dev";
1529
+ this.homePath = "~/.continue";
1530
+ }
1531
+ // ---------------------------------------------------------------
1532
+ // scan()
1533
+ // ---------------------------------------------------------------
1534
+ async scan() {
1535
+ const available = /* @__PURE__ */ new Map();
1536
+ const home = this.resolvedHomePath;
1537
+ if (!await fse7.pathExists(home)) {
1538
+ return { source: this.name, available };
1539
+ }
1540
+ const configPath = path7.join(home, "config.json");
1541
+ if (await fse7.pathExists(configPath)) {
1542
+ available.set("settings", {
1543
+ count: 1,
1544
+ description: "Continue.dev config (models, context providers, slash commands, embeddings)"
1545
+ });
1546
+ }
1547
+ return { source: this.name, available };
1548
+ }
1549
+ // ---------------------------------------------------------------
1550
+ // import()
1551
+ // ---------------------------------------------------------------
1552
+ async import(categories, onProgress) {
1553
+ const start = Date.now();
1554
+ const imported = /* @__PURE__ */ new Map();
1555
+ const errors = [];
1556
+ for (const category of categories) {
1557
+ switch (category) {
1558
+ case "settings":
1559
+ await this.importSettings(imported, errors, onProgress);
1560
+ break;
1561
+ default:
1562
+ break;
1563
+ }
1564
+ }
1565
+ return {
1566
+ source: this.name,
1567
+ imported,
1568
+ errors,
1569
+ duration: Date.now() - start
1570
+ };
1571
+ }
1572
+ // ---------------------------------------------------------------
1573
+ // Settings
1574
+ // ---------------------------------------------------------------
1575
+ async importSettings(imported, errors, onProgress) {
1576
+ const configPath = path7.join(this.resolvedHomePath, "config.json");
1577
+ if (!await fse7.pathExists(configPath)) {
1578
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
1579
+ return;
1580
+ }
1581
+ onProgress?.({
1582
+ category: "settings",
1583
+ current: 1,
1584
+ total: 1,
1585
+ item: "config.json",
1586
+ status: "importing"
1587
+ });
1588
+ try {
1589
+ const config = await this.safeReadJson(configPath);
1590
+ const extracted = {
1591
+ importedFrom: "continue",
1592
+ importedAt: (/* @__PURE__ */ new Date()).toISOString()
1593
+ };
1594
+ if (config.models) extracted.models = config.models;
1595
+ if (config.contextProviders) extracted.contextProviders = config.contextProviders;
1596
+ if (config.slashCommands) extracted.slashCommands = config.slashCommands;
1597
+ if (config.embeddingsProvider) extracted.embeddingsProvider = config.embeddingsProvider;
1598
+ const configDir = AUTOHAND_PATHS.config;
1599
+ await fse7.ensureDir(configDir);
1600
+ await fse7.writeJson(
1601
+ path7.join(configDir, "imported-continue-settings.json"),
1602
+ extracted,
1603
+ { spaces: 2 }
1604
+ );
1605
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
1606
+ onProgress?.({
1607
+ category: "settings",
1608
+ current: 1,
1609
+ total: 1,
1610
+ item: "config.json",
1611
+ status: "done"
1612
+ });
1613
+ } catch (err) {
1614
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
1615
+ errors.push({
1616
+ category: "settings",
1617
+ item: "config.json",
1618
+ error: err instanceof Error ? err.message : String(err),
1619
+ retriable: false
1620
+ });
1621
+ }
1622
+ }
1623
+ };
1624
+
1625
+ // src/import/importers/AugmentImporter.ts
1626
+ import path8 from "path";
1627
+ import fse8 from "fs-extra";
1628
+ var AugmentImporter = class extends BaseImporter {
1629
+ constructor() {
1630
+ super(...arguments);
1631
+ this.name = "augment";
1632
+ this.displayName = "Augment";
1633
+ this.homePath = "~/.augment";
1634
+ }
1635
+ // ---------------------------------------------------------------
1636
+ // scan()
1637
+ // ---------------------------------------------------------------
1638
+ async scan() {
1639
+ const available = /* @__PURE__ */ new Map();
1640
+ const home = this.resolvedHomePath;
1641
+ if (!await fse8.pathExists(home)) {
1642
+ return { source: this.name, available };
1643
+ }
1644
+ const mcpPath = path8.join(home, "mcp.json");
1645
+ if (await fse8.pathExists(mcpPath)) {
1646
+ available.set("mcp", { count: 1, description: "Augment MCP server configurations" });
1647
+ }
1648
+ const settingsPath = path8.join(home, "settings.json");
1649
+ if (await fse8.pathExists(settingsPath)) {
1650
+ available.set("settings", { count: 1, description: "Augment settings" });
1651
+ }
1652
+ return { source: this.name, available };
1653
+ }
1654
+ // ---------------------------------------------------------------
1655
+ // import()
1656
+ // ---------------------------------------------------------------
1657
+ async import(categories, onProgress) {
1658
+ const start = Date.now();
1659
+ const imported = /* @__PURE__ */ new Map();
1660
+ const errors = [];
1661
+ for (const category of categories) {
1662
+ switch (category) {
1663
+ case "mcp":
1664
+ await this.importMcp(imported, errors, onProgress);
1665
+ break;
1666
+ case "settings":
1667
+ await this.importSettings(imported, errors, onProgress);
1668
+ break;
1669
+ default:
1670
+ break;
1671
+ }
1672
+ }
1673
+ return {
1674
+ source: this.name,
1675
+ imported,
1676
+ errors,
1677
+ duration: Date.now() - start
1678
+ };
1679
+ }
1680
+ // ---------------------------------------------------------------
1681
+ // MCP
1682
+ // ---------------------------------------------------------------
1683
+ async importMcp(imported, errors, onProgress) {
1684
+ const mcpPath = path8.join(this.resolvedHomePath, "mcp.json");
1685
+ if (!await fse8.pathExists(mcpPath)) {
1686
+ imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
1687
+ return;
1688
+ }
1689
+ onProgress?.({
1690
+ category: "mcp",
1691
+ current: 1,
1692
+ total: 1,
1693
+ item: "mcp.json",
1694
+ status: "importing"
1695
+ });
1696
+ try {
1697
+ const mcpData = await this.safeReadJson(mcpPath);
1698
+ const configDir = AUTOHAND_PATHS.config;
1699
+ await fse8.ensureDir(configDir);
1700
+ await fse8.writeJson(
1701
+ path8.join(configDir, "imported-augment-mcp.json"),
1702
+ {
1703
+ importedFrom: "augment",
1704
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1705
+ mcpServers: mcpData.mcpServers ?? mcpData
1706
+ },
1707
+ { spaces: 2 }
1708
+ );
1709
+ imported.set("mcp", { success: 1, failed: 0, skipped: 0 });
1710
+ onProgress?.({
1711
+ category: "mcp",
1712
+ current: 1,
1713
+ total: 1,
1714
+ item: "mcp.json",
1715
+ status: "done"
1716
+ });
1717
+ } catch (err) {
1718
+ imported.set("mcp", { success: 0, failed: 1, skipped: 0 });
1719
+ errors.push({
1720
+ category: "mcp",
1721
+ item: "mcp.json",
1722
+ error: err instanceof Error ? err.message : String(err),
1723
+ retriable: false
1724
+ });
1725
+ }
1726
+ }
1727
+ // ---------------------------------------------------------------
1728
+ // Settings
1729
+ // ---------------------------------------------------------------
1730
+ async importSettings(imported, errors, onProgress) {
1731
+ const settingsPath = path8.join(this.resolvedHomePath, "settings.json");
1732
+ if (!await fse8.pathExists(settingsPath)) {
1733
+ imported.set("settings", { success: 0, failed: 0, skipped: 1 });
1734
+ return;
1735
+ }
1736
+ onProgress?.({
1737
+ category: "settings",
1738
+ current: 1,
1739
+ total: 1,
1740
+ item: "settings.json",
1741
+ status: "importing"
1742
+ });
1743
+ try {
1744
+ const settings = await this.safeReadJson(settingsPath);
1745
+ const configDir = AUTOHAND_PATHS.config;
1746
+ await fse8.ensureDir(configDir);
1747
+ await fse8.writeJson(
1748
+ path8.join(configDir, "imported-augment-settings.json"),
1749
+ {
1750
+ importedFrom: "augment",
1751
+ importedAt: (/* @__PURE__ */ new Date()).toISOString(),
1752
+ raw: settings
1753
+ },
1754
+ { spaces: 2 }
1755
+ );
1756
+ imported.set("settings", { success: 1, failed: 0, skipped: 0 });
1757
+ onProgress?.({
1758
+ category: "settings",
1759
+ current: 1,
1760
+ total: 1,
1761
+ item: "settings.json",
1762
+ status: "done"
1763
+ });
1764
+ } catch (err) {
1765
+ imported.set("settings", { success: 0, failed: 1, skipped: 0 });
1766
+ errors.push({
1767
+ category: "settings",
1768
+ item: "settings.json",
1769
+ error: err instanceof Error ? err.message : String(err),
1770
+ retriable: false
1771
+ });
1772
+ }
1773
+ }
1774
+ };
1775
+
1776
+ // src/import/registry.ts
1777
+ var ImporterRegistry = class {
1778
+ constructor() {
1779
+ this.importers = /* @__PURE__ */ new Map();
1780
+ this.register(new ClaudeImporter());
1781
+ this.register(new CodexImporter());
1782
+ this.register(new GeminiImporter());
1783
+ this.register(new CursorImporter());
1784
+ this.register(new ClineImporter());
1785
+ this.register(new ContinueImporter());
1786
+ this.register(new AugmentImporter());
1787
+ }
1788
+ /**
1789
+ * Register an importer instance by its source name.
1790
+ */
1791
+ register(importer) {
1792
+ this.importers.set(importer.name, importer);
1793
+ }
1794
+ /**
1795
+ * Get an importer by its source name.
1796
+ * Returns undefined if the source is not registered.
1797
+ */
1798
+ get(name) {
1799
+ return this.importers.get(name);
1800
+ }
1801
+ /**
1802
+ * Get all registered importers.
1803
+ */
1804
+ getAll() {
1805
+ return Array.from(this.importers.values());
1806
+ }
1807
+ /**
1808
+ * Detect which agent data directories exist on disk.
1809
+ * Runs all detect() calls in parallel for speed.
1810
+ */
1811
+ async detectAvailable() {
1812
+ const results = await Promise.all(
1813
+ this.getAll().map(async (importer) => ({
1814
+ importer,
1815
+ exists: await importer.detect()
1816
+ }))
1817
+ );
1818
+ return results.filter((r) => r.exists).map((r) => r.importer);
1819
+ }
1820
+ };
1821
+ export {
1822
+ ImporterRegistry
1823
+ };
1824
+ /**
1825
+ * @license
1826
+ * Copyright 2025 Autohand AI LLC
1827
+ * SPDX-License-Identifier: Apache-2.0
1828
+ */