autohand-cli 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -79
- package/dist/AgentRegistry-BBQRODQC.cjs +18 -0
- package/dist/AgentRegistry-JBXZUPML.js +18 -0
- package/dist/{CommunitySkillsCache-ZACDPD4J.js → CommunitySkillsCache-CI7UN2DX.js} +2 -2
- package/dist/CommunitySkillsCache-XTQ6RMTA.cjs +8 -0
- package/dist/{HookManager-2S6AHOC3.js → HookManager-BELBPQQI.js} +1 -1
- package/dist/{HookManager-TVEQI5ZU.cjs → HookManager-ZL2CLAJW.cjs} +2 -2
- package/dist/{ImportWizard-AF2XL6DS.cjs → ImportWizard-U6CIJREW.cjs} +12 -12
- package/dist/{ImportWizard-AEBMAKXE.js → ImportWizard-VJFSWSUQ.js} +3 -3
- package/dist/LearnAdvisor-LAURA3IB.cjs +9 -0
- package/dist/LearnAdvisor-RFOBXFG7.js +9 -0
- package/dist/MemoryManager-3A2VRPF2.js +9 -0
- package/dist/MemoryManager-UOEQZIDC.cjs +9 -0
- package/dist/{NVIDIAProvider-SJPY3ONR.js → NVIDIAProvider-AFNJNWJM.js} +1 -1
- package/dist/NVIDIAProvider-L5GTYRCQ.cjs +14 -0
- package/dist/{PermissionManager-MT7KBNNR.js → PermissionManager-N2LDSOYF.js} +3 -3
- package/dist/PermissionManager-ZNURIEYR.cjs +11 -0
- package/dist/ProviderFactory-3BFS65V7.cjs +13 -0
- package/dist/{ProviderFactory-RB4RVAF6.js → ProviderFactory-XUT6BSGB.js} +4 -3
- package/dist/SessionManager-LGPQIA57.cjs +10 -0
- package/dist/{SessionManager-554PHVPC.js → SessionManager-OR4KDDDS.js} +2 -2
- package/dist/{SkillsRegistry-NHHMIUYJ.js → SkillsRegistry-IL3GWROU.js} +2 -2
- package/dist/SkillsRegistry-PM34DQNA.cjs +9 -0
- package/dist/SubAgent-2WG4QQB5.cjs +13 -0
- package/dist/SubAgent-ICGN23TQ.js +13 -0
- package/dist/{about-3USFSGOH.js → about-OYVGQMJJ.js} +3 -3
- package/dist/{about-QR52U5DD.cjs → about-U2BH7HDR.cjs} +4 -4
- package/dist/{acp-5Y2W6OZP.js → acp-JWHGXZL5.js} +169 -103
- package/dist/{acp-GSYE75OB.cjs → acp-S37JOBCS.cjs} +184 -118
- package/dist/{actionExecutor-KHUU3Z3Q.cjs → actionExecutor-2QEPMELQ.cjs} +13 -13
- package/dist/{actionExecutor-PLQJZLZV.js → actionExecutor-6NCCORRB.js} +12 -12
- package/dist/add-dir-KFUHSIR2.cjs +11 -0
- package/dist/{add-dir-HCERJDBR.js → add-dir-MM2BM2Z2.js} +2 -2
- package/dist/agent-DUIYLIVN.js +132 -0
- package/dist/agent-YYEHGDAK.cjs +132 -0
- package/dist/agents-GBGG4CW7.cjs +19 -0
- package/dist/agents-ZH34C72F.js +19 -0
- package/dist/agents-new-ERXLS7SB.cjs +17 -0
- package/dist/{agents-new-7GAQ25EK.js → agents-new-EVTGPTA4.js} +6 -6
- package/dist/{autoSkill-66PKCYTW.js → autoSkill-HEWKJ5JV.js} +2 -2
- package/dist/autoSkill-YL6PN6AV.cjs +20 -0
- package/dist/automode-4BJ7FNPL.cjs +10 -0
- package/dist/{automode-BUF3VGXU.js → automode-S4U7A7Q2.js} +2 -2
- package/dist/chrome-45ZXHL5N.cjs +22 -0
- package/dist/{chrome-Y3T7EIHG.js → chrome-BBSRVG6S.js} +2 -2
- package/dist/chrome-IFVZRHAT.cjs +50 -0
- package/dist/chrome-MYE6DNA2.js +22 -0
- package/dist/{chunk-45CHNQM6.cjs → chunk-24CEJYEG.cjs} +93 -31
- package/dist/{chunk-6JWCGQJU.cjs → chunk-255GIVM2.cjs} +6 -6
- package/dist/{chunk-D546G7DA.cjs → chunk-2BDSR2OW.cjs} +98 -75
- package/dist/{chunk-PGFLPURU.js → chunk-2BPIR7LA.js} +121 -4
- package/dist/{chunk-AOKXYGBQ.cjs → chunk-2NY7OHBF.cjs} +41 -26
- package/dist/chunk-2WUNHTXL.js +303 -0
- package/dist/{chunk-PQBYFEBL.cjs → chunk-34B6ZO6W.cjs} +124 -7
- package/dist/{chunk-5JTTM5SC.js → chunk-3BJN7GAH.js} +1 -1
- package/dist/{chunk-3UC6DMFI.cjs → chunk-3CAXECWJ.cjs} +15 -15
- package/dist/{chunk-YWH55BWK.cjs → chunk-3CBYUBZC.cjs} +6 -9
- package/dist/chunk-3DF3GZQ7.js +277 -0
- package/dist/{chunk-KASXKDF2.cjs → chunk-3JURXAL6.cjs} +58 -7
- package/dist/{chunk-JV5HVCHU.cjs → chunk-3KWAP2Y3.cjs} +88 -9
- package/dist/{chunk-WPE2XHVX.js → chunk-3MCK6UBL.js} +1 -1
- package/dist/{chunk-U2QUMKCB.js → chunk-3TH7IK4M.js} +62 -9
- package/dist/{chunk-YXM6SA7P.js → chunk-3V77OB3W.js} +3 -3
- package/dist/{chunk-MZN6JBRZ.cjs → chunk-3Y5UEK7K.cjs} +4 -4
- package/dist/{chunk-BP37FVBM.js → chunk-4GPPSBEZ.js} +3 -3
- package/dist/{chunk-4XVLNOFA.js → chunk-5CMBAJ6K.js} +20 -3
- package/dist/{chunk-PNIAIOMZ.cjs → chunk-5YRXFBYZ.cjs} +35 -6
- package/dist/chunk-6AC2TT26.js +156 -0
- package/dist/{chunk-PSAH4ZQB.cjs → chunk-6EIQ6A6U.cjs} +2 -2
- package/dist/{chunk-YQDI753V.js → chunk-6HSEDXVF.js} +4 -4
- package/dist/{chunk-O5GI6SR3.js → chunk-6NUXK62F.js} +1 -1
- package/dist/{chunk-HVCIB4SW.cjs → chunk-6TGCAPYH.cjs} +62 -9
- package/dist/{chunk-HZWU6IO3.js → chunk-6W3SZCSP.js} +2 -5
- package/dist/{chunk-Q3BS6FPM.js → chunk-73LV3DDZ.js} +4 -4
- package/dist/{chunk-ZNGRLCFQ.js → chunk-7BGGLIQF.js} +83 -1
- package/dist/{chunk-ZNYZB7XY.cjs → chunk-7EEK7CRR.cjs} +83 -1
- package/dist/{chunk-HK5A54AV.cjs → chunk-7TO3PDMV.cjs} +48 -4
- package/dist/chunk-7UU22RSH.cjs +277 -0
- package/dist/{chunk-XNIMSVS6.cjs → chunk-A3GAM6FM.cjs} +11 -11
- package/dist/{chunk-W5QLA6WP.cjs → chunk-A7DJU75T.cjs} +8 -8
- package/dist/{chunk-7XTUL7ZD.cjs → chunk-AAAO4ERQ.cjs} +9 -9
- package/dist/{chunk-M5DK524Z.js → chunk-AAJLMP57.js} +2 -2
- package/dist/chunk-ABR756QN.js +529 -0
- package/dist/{chunk-OIGYWOL6.js → chunk-APFGDIPD.js} +3 -1
- package/dist/{chunk-PTTZI4QZ.js → chunk-APQYRMYL.js} +4 -4
- package/dist/{chunk-CO2AADYU.cjs → chunk-AZKOIF2G.cjs} +55 -17
- package/dist/{chunk-P6SLT2F4.cjs → chunk-AZLHUPNC.cjs} +2 -2
- package/dist/chunk-B55VCYSQ.cjs +30 -0
- package/dist/{chunk-JMJRFSNJ.js → chunk-BLQUMSM3.js} +1 -1
- package/dist/{chunk-MGNXABSU.cjs → chunk-BXKPX6K4.cjs} +9 -9
- package/dist/{chunk-MQQH4XQH.cjs → chunk-C66FN2LP.cjs} +4 -4
- package/dist/{chunk-CECH6QQP.js → chunk-CH7KUFAS.js} +10 -10
- package/dist/{chunk-PIXQ2AVM.cjs → chunk-CILSXOPI.cjs} +17 -17
- package/dist/{chunk-IEPLQ47J.js → chunk-CM24K6ZT.js} +89 -12
- package/dist/chunk-CMEZ42F2.cjs +303 -0
- package/dist/{chunk-X5P6QQOB.cjs → chunk-CNQKIWIS.cjs} +100 -23
- package/dist/{chunk-AQ5PVHOC.cjs → chunk-CSUGNNJY.cjs} +4 -3
- package/dist/{chunk-QRQF3556.js → chunk-D6HB3H3L.js} +25 -10
- package/dist/{chunk-XZVDYC5U.js → chunk-D7AYKVKW.js} +2 -2
- package/dist/{chunk-3UHRCHKB.cjs → chunk-DLCXWOWT.cjs} +23 -23
- package/dist/{chunk-CK4HAHVY.cjs → chunk-DMM2BKSV.cjs} +118 -25
- package/dist/{chunk-SPQ7QIQ6.js → chunk-DW3DPV77.js} +1 -1
- package/dist/chunk-ECQD2QC3.cjs +33 -0
- package/dist/{chunk-SNDDZG5H.js → chunk-EEYOS3UC.js} +90 -70
- package/dist/{chunk-DGBPWODD.js → chunk-EF2EN5CR.js} +2 -2
- package/dist/{chunk-M7B7RRBK.cjs → chunk-EFXFURDY.cjs} +138 -51
- package/dist/chunk-EK34UZPB.cjs +40 -0
- package/dist/{chunk-CRTCZ4WL.cjs → chunk-FJR6EZLO.cjs} +3834 -2337
- package/dist/{chunk-TYBPTKFT.js → chunk-FPO7YNPQ.js} +1 -1
- package/dist/{chunk-X3TI5TJJ.js → chunk-FS4I6BNR.js} +1 -1
- package/dist/{chunk-WNJXIACY.js → chunk-FSJ2MNOC.js} +3 -3
- package/dist/{chunk-44ZWOBTI.js → chunk-GEHZMC4G.js} +12 -9
- package/dist/{chunk-Y5BDE24P.cjs → chunk-GO6C2RAR.cjs} +3 -0
- package/dist/{chunk-XW3XCK4E.cjs → chunk-GSMR6V36.cjs} +4 -4
- package/dist/{chunk-H426KOGY.js → chunk-GSZWATME.js} +1 -1
- package/dist/{chunk-S5JNQIGL.cjs → chunk-GYLGCR6F.cjs} +5 -5
- package/dist/{chunk-ONVYXTUT.cjs → chunk-H3OOWNYQ.cjs} +3 -3
- package/dist/{chunk-V5ELP2XE.js → chunk-H65446XW.js} +110 -15
- package/dist/{chunk-LANGD5CO.js → chunk-H7HXRRHK.js} +45 -1
- package/dist/{chunk-RBXBH6EB.cjs → chunk-HN2JTDN5.cjs} +17 -17
- package/dist/{chunk-SOVR7S3T.cjs → chunk-HNXUZ5OY.cjs} +2 -2
- package/dist/{chunk-AZ47LKD5.cjs → chunk-HOYT3E65.cjs} +3 -3
- package/dist/{chunk-P4FUTSVK.js → chunk-HTPY5ESD.js} +3 -3
- package/dist/{chunk-5SFV2NCY.cjs → chunk-HVLWH2AF.cjs} +10 -10
- package/dist/{chunk-VQHSYAPZ.cjs → chunk-HZTEU4W5.cjs} +62 -93
- package/dist/{chunk-4XFHP2SN.cjs → chunk-I5T7LPFP.cjs} +7 -7
- package/dist/{chunk-ZPLCAXJW.js → chunk-IB5CJXE7.js} +7 -7
- package/dist/{chunk-KM7R5YPS.cjs → chunk-INNXFLDR.cjs} +9 -6
- package/dist/{chunk-2ESQR35E.cjs → chunk-JFLEP3T7.cjs} +10 -10
- package/dist/chunk-JJGDOBFL.js +40 -0
- package/dist/{chunk-5A7ZL64N.js → chunk-JSU46T6K.js} +1 -1
- package/dist/{chunk-NB6M6ESM.js → chunk-K6WN6BT4.js} +1 -1
- package/dist/{chunk-QQ64HEHP.cjs → chunk-KIQH3SMT.cjs} +34 -31
- package/dist/{chunk-MANJ67D3.js → chunk-KPRXHIE2.js} +52 -83
- package/dist/{chunk-6HF6XSCC.js → chunk-LIO3RX2Z.js} +2 -2
- package/dist/{chunk-NZ3ZWLUW.js → chunk-LOSXLH7P.js} +109 -16
- package/dist/{chunk-NZ7GCK7Y.cjs → chunk-LSOR72PB.cjs} +23 -23
- package/dist/{chunk-6AYJCDTA.js → chunk-MA3AVDCC.js} +47 -9
- package/dist/{chunk-PZZMIYII.js → chunk-ME3S2WIR.js} +3 -3
- package/dist/{chunk-2IW5YFJ4.js → chunk-NC2I2M4P.js} +4 -4
- package/dist/{chunk-AE2ILW25.cjs → chunk-NC4A4LVC.cjs} +13 -13
- package/dist/{chunk-EEHWALXA.js → chunk-NGEK5FCJ.js} +85 -3
- package/dist/{chunk-MMKZSJUN.js → chunk-NKW6CHXQ.js} +1 -1
- package/dist/{chunk-JB3JCYBJ.js → chunk-NOWCRKP2.js} +4 -3
- package/dist/{chunk-3ZOOH44N.js → chunk-NUB2LMB6.js} +2 -2
- package/dist/chunk-O246MKIW.cjs +267 -0
- package/dist/{chunk-SRMGWMQO.js → chunk-OGFWL2PS.js} +1 -1
- package/dist/{chunk-YISPVAXO.cjs → chunk-ONNGAR6W.cjs} +340 -597
- package/dist/{chunk-7WAUCLLQ.js → chunk-OOFR6A62.js} +33 -4
- package/dist/{chunk-4E7SHPNQ.js → chunk-OZ7FHO7J.js} +2 -2
- package/dist/{chunk-NV6LCD2I.cjs → chunk-P5EWGUI2.cjs} +109 -27
- package/dist/{chunk-YC5OBZQU.js → chunk-P6BQJPAI.js} +41 -18
- package/dist/{chunk-SHRLFX6F.js → chunk-PG2JIU5M.js} +57 -6
- package/dist/{chunk-6OECOAK5.cjs → chunk-PI27G2ED.cjs} +25 -8
- package/dist/{chunk-TR6NECEZ.js → chunk-PI7LRPL6.js} +1 -1
- package/dist/{chunk-GAOPJ5S3.cjs → chunk-PMPEC5HN.cjs} +18 -15
- package/dist/{chunk-5GCQ5UMV.cjs → chunk-PYUP7AKY.cjs} +14 -14
- package/dist/{chunk-S5QKRA2V.js → chunk-QC5Z3ZT5.js} +2 -2
- package/dist/chunk-QDO4L2A7.cjs +156 -0
- package/dist/{chunk-LFDPTJYF.cjs → chunk-QDXRI5AM.cjs} +1 -1
- package/dist/{chunk-26G7YGOW.js → chunk-QVXMSQOG.js} +84 -21
- package/dist/{chunk-SVVP4UUZ.cjs → chunk-R4UKBKDY.cjs} +11 -11
- package/dist/{chunk-HG3ZASBH.cjs → chunk-R75AWII3.cjs} +112 -17
- package/dist/{chunk-TE4SYTWR.cjs → chunk-RD5PLUIX.cjs} +8 -8
- package/dist/{chunk-FFHSCM5M.js → chunk-RGB34CV5.js} +3 -3
- package/dist/{chunk-SY2P3Z5W.cjs → chunk-RJCZLFHE.cjs} +96 -32
- package/dist/{chunk-22SCR3EV.cjs → chunk-RKWNM2BJ.cjs} +2 -2
- package/dist/{chunk-FBQJZKFX.js → chunk-RMVONICR.js} +3 -3
- package/dist/{chunk-PY73W5MQ.cjs → chunk-RPSYRJL7.cjs} +10 -4
- package/dist/{chunk-HXHE2KAO.js → chunk-RWKU2X7O.js} +7 -4
- package/dist/{chunk-NQZH5CR2.cjs → chunk-RZLEGVMH.cjs} +102 -5
- package/dist/{chunk-KMP6Y3LJ.js → chunk-S2L3Y677.js} +1 -1
- package/dist/{chunk-GSDV75A5.js → chunk-S7KVUIOS.js} +1 -1
- package/dist/{chunk-7PT646AL.cjs → chunk-SACJJ6NO.cjs} +5 -3
- package/dist/{chunk-LEZEWKPA.js → chunk-SJQU2ZFR.js} +96 -32
- package/dist/{chunk-65LRPW5W.js → chunk-SKAQKQFF.js} +12 -2
- package/dist/chunk-T4DXP5OP.js +30 -0
- package/dist/{chunk-EYHKL4QC.js → chunk-T6FTB6K2.js} +1 -1
- package/dist/{chunk-DNSD7DVJ.js → chunk-T6N6GRFT.js} +13 -10
- package/dist/{chunk-575PXZX7.js → chunk-TJFKA6A7.js} +82 -3
- package/dist/{chunk-HSWWM6AM.js → chunk-TJZUPS4Z.js} +34 -291
- package/dist/{chunk-DHUQZ53B.cjs → chunk-TLKHZ425.cjs} +2 -2
- package/dist/{chunk-VLGGMQUN.cjs → chunk-TQ24NLXO.cjs} +6 -6
- package/dist/{chunk-LUMV3DB2.js → chunk-TWBAU46X.js} +1 -1
- package/dist/{chunk-EA2MS25U.cjs → chunk-TZB5XADL.cjs} +4 -4
- package/dist/{chunk-U6PLSPMD.cjs → chunk-UAYXZXWU.cjs} +4 -4
- package/dist/{chunk-OV3T5MUH.cjs → chunk-UKBFNBDO.cjs} +11 -11
- package/dist/{chunk-SZD45IDG.js → chunk-UMJYX5KD.js} +101 -4
- package/dist/{chunk-B76FJKEJ.cjs → chunk-USKYTHDL.cjs} +69 -18
- package/dist/{chunk-NZQFKXM3.cjs → chunk-VAJUSZMC.cjs} +15 -15
- package/dist/{chunk-SDLY4X3G.js → chunk-VGQG4NBJ.js} +2 -2
- package/dist/{chunk-KWXGDSYT.js → chunk-VLUIVJ3J.js} +58 -7
- package/dist/{chunk-KJ26T7GM.cjs → chunk-VOBINVMV.cjs} +105 -42
- package/dist/{chunk-C5QIQQ37.js → chunk-VSHKKCSH.js} +16 -5
- package/dist/{chunk-L46OUKW5.cjs → chunk-VSZU3MGA.cjs} +28 -17
- package/dist/{chunk-YFXTE422.cjs → chunk-VWHAUB77.cjs} +8 -3
- package/dist/{chunk-UWZ4G3SQ.js → chunk-VXGYFX45.js} +4 -4
- package/dist/{chunk-C46B72VK.js → chunk-WH6YUQDB.js} +141 -54
- package/dist/{chunk-SFFEKZGC.js → chunk-WQ6TD55V.js} +2 -2
- package/dist/{chunk-7PJKTSRN.js → chunk-WQWECXTY.js} +3 -3
- package/dist/{chunk-DSSCERHI.cjs → chunk-WVDJUJH6.cjs} +2 -2
- package/dist/{chunk-JPFRI4L4.js → chunk-X24VIVDZ.js} +210 -26
- package/dist/{chunk-7IRQ7JEH.js → chunk-X4NRTLXD.js} +7 -1
- package/dist/{chunk-7MY4JHER.js → chunk-X53SHYCG.js} +2 -2
- package/dist/{chunk-RFUKZIJF.cjs → chunk-XB2Z4ZAK.cjs} +5 -5
- package/dist/{chunk-WJYFLQ7G.cjs → chunk-Y47OJGLB.cjs} +3 -3
- package/dist/{chunk-HC2Q6A3E.cjs → chunk-Y4MN27V3.cjs} +361 -177
- package/dist/{chunk-ZK6HOR62.js → chunk-YEHFYZFU.js} +7 -2
- package/dist/{chunk-FFBDRUO5.cjs → chunk-YICIUY23.cjs} +1 -1
- package/dist/{chunk-63ANVAOJ.cjs → chunk-YMXYC777.cjs} +3 -3
- package/dist/{chunk-X7XMITIL.cjs → chunk-Z3GRWK6O.cjs} +8 -8
- package/dist/{chunk-3ICORF7M.cjs → chunk-Z5GG2KSL.cjs} +4 -4
- package/dist/{chunk-I2ZK3AOD.js → chunk-ZER7DYQK.js} +2 -2
- package/dist/{chunk-V3SZLWEQ.cjs → chunk-ZFDXZEZJ.cjs} +11 -11
- package/dist/{chunk-QBYGMMDD.js → chunk-ZFV4HJA6.js} +66 -4
- package/dist/chunk-ZHMYTI5D.cjs +529 -0
- package/dist/{chunk-4567QNRB.js → chunk-ZLR2TFBC.js} +3 -0
- package/dist/{chunk-OCATAKXV.cjs → chunk-ZTWNU5QZ.cjs} +20 -20
- package/dist/{chunk-CCIDL4SA.js → chunk-ZVLVLDYN.js} +2915 -1418
- package/dist/clear-AJGXD2BB.cjs +12 -0
- package/dist/{clear-Y5TO3RZA.js → clear-HAHDSWKW.js} +3 -3
- package/dist/communityInstaller-IRR6M3N6.cjs +22 -0
- package/dist/{communityInstaller-RVL4STPS.js → communityInstaller-OLKEUGMX.js} +5 -5
- package/dist/completion-G7Z436TF.cjs +17 -0
- package/dist/{completion-SE3XYG74.js → completion-ZS3AXJ6A.js} +4 -4
- package/dist/{config-7KPHKFTP.js → config-OWYAQPCX.js} +5 -4
- package/dist/config-W2BHT2QE.cjs +22 -0
- package/dist/{constants-EJFAWJQI.js → constants-AS6K67AA.js} +5 -3
- package/dist/constants-B4W5BT7F.cjs +23 -0
- package/dist/{export-BJVIDZC4.js → export-5HIU3KMD.js} +4 -4
- package/dist/export-GFD32UY2.cjs +15 -0
- package/dist/{extractSessionMemories-A2JX5WJ2.js → extractSessionMemories-K6ZVAW2F.js} +1 -1
- package/dist/{extractSessionMemories-XL3MS37F.cjs → extractSessionMemories-LLOIJR5U.cjs} +2 -2
- package/dist/feature-KP74CZ3F.cjs +14 -0
- package/dist/{feature-V4JF5TNJ.js → feature-OPNVMB2E.js} +2 -2
- package/dist/features-LT55MURX.cjs +24 -0
- package/dist/features-ZDIU26WX.js +24 -0
- package/dist/feedback-7WTJFQ6S.js +18 -0
- package/dist/feedback-CEOJ3453.cjs +18 -0
- package/dist/go-2CY5SZNR.js +16 -0
- package/dist/go-O2CSQON4.cjs +16 -0
- package/dist/goal-DL2N2AWT.cjs +16 -0
- package/dist/goal-IJS7VZSG.js +16 -0
- package/dist/help-RNOGDEBA.cjs +12 -0
- package/dist/{help-MLIROWKM.js → help-TCWD2IRH.js} +2 -2
- package/dist/{history-GQJ6RZD6.js → history-ATOR5OQV.js} +2 -2
- package/dist/history-UUSGX2AL.cjs +14 -0
- package/dist/{hooks-PPFHCF7T.js → hooks-R3Z5QKUP.js} +5 -5
- package/dist/hooks-RWM5UY67.cjs +18 -0
- package/dist/{i18n-Q7UZJRPL.js → i18n-4QI4TD4I.js} +1 -1
- package/dist/i18n-MFAEU5RV.cjs +33 -0
- package/dist/{ide-BUSVE54P.js → ide-6PBTCCUQ.js} +4 -4
- package/dist/ide-UE3G7NMQ.cjs +15 -0
- package/dist/{import-C7S6UJMW.cjs → import-2IG76KAN.cjs} +6 -4
- package/dist/{import-U47DXCA7.js → import-E47QL4DW.js} +2 -2
- package/dist/import-NQDNBFUL.cjs +10 -0
- package/dist/{import-3VBKI6BN.js → import-VQIHGJWS.js} +6 -4
- package/dist/index.cjs +444 -334
- package/dist/index.d.cts +38 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +324 -214
- package/dist/init-DX3RDGDT.cjs +10 -0
- package/dist/{init-Q2O4R42R.js → init-Q54OAAFZ.js} +2 -2
- package/dist/{inputPrompt-3CFZDUBH.js → inputPrompt-V2VBDRM7.js} +2 -2
- package/dist/inputPrompt-WVGVWAHS.cjs +90 -0
- package/dist/language-I6KXAOXD.js +23 -0
- package/dist/language-XMIVOH5E.cjs +23 -0
- package/dist/learn-JPVVGTKU.js +23 -0
- package/dist/learn-NLSHI2MZ.cjs +23 -0
- package/dist/login-NABQYLYC.cjs +28 -0
- package/dist/login-XPOVFSWN.js +28 -0
- package/dist/logout-HNHCGB4Q.js +25 -0
- package/dist/logout-SKGDXJSW.cjs +25 -0
- package/dist/{mcp-AH3MMUBU.js → mcp-EN73YFGZ.js} +8 -7
- package/dist/mcp-TADZCPJQ.cjs +22 -0
- package/dist/{mcp-install-IA4ZS2SV.cjs → mcp-install-2GKWWBAS.cjs} +14 -13
- package/dist/{mcp-install-222PCKSW.js → mcp-install-3TBTVSHW.js} +9 -8
- package/dist/memory-GRXFTDIN.cjs +10 -0
- package/dist/{memory-VB46T5H3.js → memory-K2P3CDCH.js} +2 -2
- package/dist/{model-SJJG64AM.js → model-DEG22OWA.js} +2 -2
- package/dist/model-OSD74T7Z.cjs +10 -0
- package/dist/new-4NWBOATU.cjs +12 -0
- package/dist/{new-ERZ5C6CN.js → new-KJAP2MB6.js} +3 -3
- package/dist/{onboarding-ZQXMPSMJ.js → onboarding-2U5WE2OA.js} +17 -14
- package/dist/onboarding-5DZFCO5Q.cjs +39 -0
- package/dist/permissions-KY5I6YQ3.cjs +10 -0
- package/dist/{permissions-7ACNFK7A.js → permissions-TKYON7PP.js} +2 -2
- package/dist/{plan-YYUAXPTL.js → plan-DYHHLZSS.js} +1 -1
- package/dist/plan-PYKP652W.cjs +13 -0
- package/dist/quit-GSKJL42O.js +14 -0
- package/dist/quit-TQSRTBUT.cjs +14 -0
- package/dist/{registry-4DXUDKJN.js → registry-EZ4V4TUQ.js} +1339 -1
- package/dist/{registry-UEO3ETZ7.cjs → registry-LCWYI4IB.cjs} +1378 -40
- package/dist/resume-4VWJXARX.cjs +17 -0
- package/dist/{resume-XSXZMDMD.js → resume-TLHWWWFN.js} +5 -5
- package/dist/{review-QHP2KP4Q.js → review-CSK4IYTO.js} +1 -1
- package/dist/review-XLJEUH5K.cjs +9 -0
- package/dist/{rpc-XH7QLN4H.js → rpc-3DLQBDWU.js} +151 -124
- package/dist/{rpc-YF54T7JU.cjs → rpc-O36WUU3L.cjs} +169 -142
- package/dist/search-DSX2CY4A.cjs +22 -0
- package/dist/search-I3QUDUQL.js +22 -0
- package/dist/sessionBranching-DVNOUWJT.cjs +19 -0
- package/dist/sessionBranching-FKV4CR36.js +19 -0
- package/dist/sessions-3JUOT3ED.cjs +10 -0
- package/dist/{sessions-NJYHJOEL.js → sessions-VWMDIPOS.js} +2 -2
- package/dist/{settings-ZXUQH3DO.js → settings-FT2LZZUV.js} +11 -8
- package/dist/settings-RL4KNWHB.cjs +45 -0
- package/dist/setup-HQEJVOYT.js +32 -0
- package/dist/setup-MN54LKOL.cjs +32 -0
- package/dist/share-BUAFZNBX.cjs +17 -0
- package/dist/{share-WFAGZ5PY.js → share-CGB6MAVJ.js} +6 -6
- package/dist/skills/builtin/code-reviewer/SKILL.md +64 -0
- package/dist/skills/builtin/goal-writer/SKILL.md +124 -0
- package/dist/{skills-NBTNDVAY.js → skills-7DKR3HRZ.js} +7 -7
- package/dist/{skills-OB6RDW7D.js → skills-BBBENOEY.js} +9 -9
- package/dist/skills-OQM7IHAF.cjs +29 -0
- package/dist/{skills-ZROBG3RZ.cjs → skills-RA2PKL63.cjs} +9 -9
- package/dist/{skills-install-ILX6QVEF.cjs → skills-install-D7K476SL.cjs} +15 -15
- package/dist/{skills-install-BHTIEMKH.js → skills-install-T4SOKJSL.js} +8 -8
- package/dist/{skills-new-YMRP2HNO.js → skills-new-S33NGEU3.js} +6 -6
- package/dist/skills-new-UVYH53MD.cjs +18 -0
- package/dist/slashCommands-MWOUDSQP.js +111 -0
- package/dist/slashCommands-XASURUTV.cjs +111 -0
- package/dist/squad-PIIYDFVH.cjs +15 -0
- package/dist/squad-VHYOVEJP.js +15 -0
- package/dist/status-GHFTXQBL.js +25 -0
- package/dist/status-WXMIJIU3.cjs +25 -0
- package/dist/statusline-2K7AC6ZQ.js +21 -0
- package/dist/statusline-GROI4HOC.cjs +21 -0
- package/dist/sync-254WF6JI.cjs +42 -0
- package/dist/sync-2DIZN4EH.cjs +24 -0
- package/dist/{sync-OCJN4ZSO.js → sync-J6I2ZUKQ.js} +5 -3
- package/dist/{sync-7C25MOT2.js → sync-Z3LVSEEV.js} +8 -6
- package/dist/{teammate-D77B6QRT.cjs → teammate-EXR76PEQ.cjs} +5 -5
- package/dist/{teammate-EZCMHOIL.js → teammate-K4DAOFEQ.js} +5 -5
- package/dist/theme-MVQDSU47.js +23 -0
- package/dist/theme-QAKEYWJG.cjs +23 -0
- package/dist/ui/questionModal.cjs +5 -5
- package/dist/ui/questionModal.js +4 -4
- package/dist/{undo-GNUTFXCW.js → undo-5AU47JHF.js} +2 -2
- package/dist/undo-ME6WKUXZ.cjs +10 -0
- package/dist/{usage-QSTNSDAO.js → usage-QTKO2YMD.js} +6 -5
- package/dist/usage-TYNJKVER.cjs +25 -0
- package/package.json +4 -3
- package/dist/AgentRegistry-GOV7FN2O.js +0 -10
- package/dist/AgentRegistry-J2C6JBZ3.cjs +0 -10
- package/dist/CommunitySkillsCache-22BB3J6H.cjs +0 -8
- package/dist/LearnAdvisor-KKEQ5QCV.js +0 -9
- package/dist/LearnAdvisor-Q7RAYLPF.cjs +0 -9
- package/dist/MemoryManager-PMNAEZMB.cjs +0 -8
- package/dist/MemoryManager-QZRLTUB5.js +0 -8
- package/dist/NVIDIAProvider-C3FWQOBZ.cjs +0 -14
- package/dist/PermissionManager-URCNP5EC.cjs +0 -11
- package/dist/ProviderFactory-56N3ECE4.cjs +0 -12
- package/dist/SessionManager-2IZGWASQ.cjs +0 -10
- package/dist/SkillsRegistry-GMRVONOQ.cjs +0 -9
- package/dist/SubAgent-4GOR2FIJ.js +0 -13
- package/dist/SubAgent-ZJMDH4FI.cjs +0 -13
- package/dist/add-dir-BTAD5OZS.cjs +0 -11
- package/dist/agent-B3EVT7NN.cjs +0 -126
- package/dist/agent-SATQ3WZ3.js +0 -126
- package/dist/agents-44CRJGM7.cjs +0 -18
- package/dist/agents-NN4ZAJ7R.js +0 -18
- package/dist/agents-new-6D6G4QS6.cjs +0 -17
- package/dist/autoSkill-VQLGBELN.cjs +0 -20
- package/dist/automode-45DWV4TN.cjs +0 -10
- package/dist/chrome-Q2U73HZB.cjs +0 -50
- package/dist/chrome-Q54OALOK.cjs +0 -21
- package/dist/chrome-ZNJ46OYW.js +0 -21
- package/dist/chunk-JCUHCH37.cjs +0 -247
- package/dist/chunk-VKOXFT4L.cjs +0 -23
- package/dist/clear-QJXU25IF.cjs +0 -12
- package/dist/communityInstaller-LXMVKVAV.cjs +0 -22
- package/dist/completion-JX4T2ONW.cjs +0 -17
- package/dist/config-3224PRW4.cjs +0 -21
- package/dist/constants-MCCGUU5F.cjs +0 -21
- package/dist/export-KU4557HK.cjs +0 -15
- package/dist/feature-K3LG5IJP.cjs +0 -14
- package/dist/features-5OJTLKS7.js +0 -23
- package/dist/features-VCBJQXCX.cjs +0 -23
- package/dist/feedback-D4437VE4.js +0 -18
- package/dist/feedback-VZPEHGFY.cjs +0 -18
- package/dist/go-X4E6BCD6.js +0 -12
- package/dist/go-XREVFS5I.cjs +0 -12
- package/dist/goal-4M3J6JS2.cjs +0 -16
- package/dist/goal-EI66BV7W.js +0 -16
- package/dist/help-GGFS7WHY.cjs +0 -12
- package/dist/history-J4LUIOSI.cjs +0 -14
- package/dist/hooks-FSRIUS6A.cjs +0 -18
- package/dist/i18n-CI6VFXL5.cjs +0 -33
- package/dist/ide-YR27BPGM.cjs +0 -15
- package/dist/import-DBK4OCDF.cjs +0 -10
- package/dist/init-OXTYS72D.cjs +0 -10
- package/dist/inputPrompt-JMACL4EB.cjs +0 -90
- package/dist/language-EK3M6UBV.cjs +0 -22
- package/dist/language-Q3RUGGOW.js +0 -22
- package/dist/learn-3DSX7DYG.cjs +0 -23
- package/dist/learn-OPOH5L43.js +0 -23
- package/dist/login-GST7MWXJ.cjs +0 -27
- package/dist/login-Q7DZKAX4.js +0 -27
- package/dist/logout-2G7OUK7I.cjs +0 -24
- package/dist/logout-FNBBL2UI.js +0 -24
- package/dist/mcp-DW7R63IB.cjs +0 -21
- package/dist/memory-6NX3DAIY.cjs +0 -10
- package/dist/model-64NAELFS.cjs +0 -10
- package/dist/new-DU5SOOOY.cjs +0 -12
- package/dist/onboarding-2U2BV2KE.cjs +0 -36
- package/dist/permissions-GSNNV7RJ.cjs +0 -10
- package/dist/plan-XEJMOT55.cjs +0 -13
- package/dist/quit-WY6T267G.js +0 -10
- package/dist/quit-XIRE2KRE.cjs +0 -10
- package/dist/resume-RQZ3WXBP.cjs +0 -17
- package/dist/review-UWHWQHCB.cjs +0 -9
- package/dist/search-VXXFGZWU.cjs +0 -21
- package/dist/search-YAWGX7P7.js +0 -21
- package/dist/sessions-OSG3UJEZ.cjs +0 -10
- package/dist/settings-SO2UIGWV.cjs +0 -42
- package/dist/setup-KG7EGKF5.js +0 -30
- package/dist/setup-RSOPCQ57.cjs +0 -30
- package/dist/share-ZU3SGACF.cjs +0 -17
- package/dist/skills-KBVAQAD2.cjs +0 -29
- package/dist/skills-new-B45VQ2PP.cjs +0 -18
- package/dist/slashCommands-53VYIBJU.js +0 -105
- package/dist/slashCommands-BG2RGGZ6.cjs +0 -105
- package/dist/status-CQ2IUOVK.cjs +0 -24
- package/dist/status-E7IGNVPC.js +0 -24
- package/dist/sync-XRP46IVG.cjs +0 -40
- package/dist/sync-ZMFVE7T4.cjs +0 -22
- package/dist/theme-KKRDE6P7.cjs +0 -22
- package/dist/theme-XF7XIWBQ.js +0 -22
- package/dist/undo-U4KN7QQM.cjs +0 -10
- package/dist/usage-YDEMQBNQ.cjs +0 -24
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AUTOHAND_PATHS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PG2JIU5M.js";
|
|
4
4
|
import "./chunk-QGM4M3NI.js";
|
|
5
5
|
|
|
6
6
|
// src/import/importers/ClaudeImporter.ts
|
|
@@ -1024,6 +1024,13 @@ var GeminiImporter = class extends BaseImporter {
|
|
|
1024
1024
|
});
|
|
1025
1025
|
}
|
|
1026
1026
|
}
|
|
1027
|
+
const mcpServers = this.extractMcpServers(settings);
|
|
1028
|
+
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
1029
|
+
available.set("mcp", {
|
|
1030
|
+
count: Object.keys(mcpServers).length,
|
|
1031
|
+
description: `${Object.keys(mcpServers).length} Gemini MCP server${Object.keys(mcpServers).length !== 1 ? "s" : ""}`
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1027
1034
|
} catch {
|
|
1028
1035
|
}
|
|
1029
1036
|
}
|
|
@@ -1048,6 +1055,9 @@ var GeminiImporter = class extends BaseImporter {
|
|
|
1048
1055
|
case "hooks":
|
|
1049
1056
|
await this.importHooks(imported, errors, onProgress);
|
|
1050
1057
|
break;
|
|
1058
|
+
case "mcp":
|
|
1059
|
+
await this.importMcp(imported, errors, onProgress);
|
|
1060
|
+
break;
|
|
1051
1061
|
case "memory":
|
|
1052
1062
|
await this.importMemory(imported, errors, onProgress);
|
|
1053
1063
|
break;
|
|
@@ -1162,6 +1172,58 @@ var GeminiImporter = class extends BaseImporter {
|
|
|
1162
1172
|
}
|
|
1163
1173
|
}
|
|
1164
1174
|
// ---------------------------------------------------------------
|
|
1175
|
+
// MCP
|
|
1176
|
+
// ---------------------------------------------------------------
|
|
1177
|
+
async importMcp(imported, errors, onProgress) {
|
|
1178
|
+
const settingsPath = path4.join(this.resolvedHomePath, "settings.json");
|
|
1179
|
+
if (!await fse4.pathExists(settingsPath)) {
|
|
1180
|
+
imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
onProgress?.({
|
|
1184
|
+
category: "mcp",
|
|
1185
|
+
current: 1,
|
|
1186
|
+
total: 1,
|
|
1187
|
+
item: "mcpServers from settings.json",
|
|
1188
|
+
status: "importing"
|
|
1189
|
+
});
|
|
1190
|
+
try {
|
|
1191
|
+
const settings = await this.safeReadJson(settingsPath);
|
|
1192
|
+
const mcpServers = this.extractMcpServers(settings);
|
|
1193
|
+
if (!mcpServers || Object.keys(mcpServers).length === 0) {
|
|
1194
|
+
imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
const configDir = AUTOHAND_PATHS.config;
|
|
1198
|
+
await fse4.ensureDir(configDir);
|
|
1199
|
+
await fse4.writeJson(
|
|
1200
|
+
path4.join(configDir, "imported-gemini-mcp.json"),
|
|
1201
|
+
{
|
|
1202
|
+
importedFrom: "gemini",
|
|
1203
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1204
|
+
mcpServers
|
|
1205
|
+
},
|
|
1206
|
+
{ spaces: 2 }
|
|
1207
|
+
);
|
|
1208
|
+
imported.set("mcp", { success: 1, failed: 0, skipped: 0 });
|
|
1209
|
+
onProgress?.({
|
|
1210
|
+
category: "mcp",
|
|
1211
|
+
current: 1,
|
|
1212
|
+
total: 1,
|
|
1213
|
+
item: "mcpServers from settings.json",
|
|
1214
|
+
status: "done"
|
|
1215
|
+
});
|
|
1216
|
+
} catch (err) {
|
|
1217
|
+
imported.set("mcp", { success: 0, failed: 1, skipped: 0 });
|
|
1218
|
+
errors.push({
|
|
1219
|
+
category: "mcp",
|
|
1220
|
+
item: "mcpServers from settings.json",
|
|
1221
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1222
|
+
retriable: false
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
// ---------------------------------------------------------------
|
|
1165
1227
|
// Memory
|
|
1166
1228
|
// ---------------------------------------------------------------
|
|
1167
1229
|
async importMemory(imported, errors, onProgress) {
|
|
@@ -1199,6 +1261,20 @@ var GeminiImporter = class extends BaseImporter {
|
|
|
1199
1261
|
});
|
|
1200
1262
|
}
|
|
1201
1263
|
}
|
|
1264
|
+
extractMcpServers(settings) {
|
|
1265
|
+
const direct = settings.mcpServers;
|
|
1266
|
+
if (direct && typeof direct === "object" && !Array.isArray(direct)) {
|
|
1267
|
+
return direct;
|
|
1268
|
+
}
|
|
1269
|
+
const mcp = settings.mcp;
|
|
1270
|
+
if (mcp && typeof mcp === "object" && !Array.isArray(mcp)) {
|
|
1271
|
+
const maybeServers = mcp.servers ?? mcp.mcpServers;
|
|
1272
|
+
if (maybeServers && typeof maybeServers === "object" && !Array.isArray(maybeServers)) {
|
|
1273
|
+
return maybeServers;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
return void 0;
|
|
1277
|
+
}
|
|
1202
1278
|
};
|
|
1203
1279
|
|
|
1204
1280
|
// src/import/importers/CursorImporter.ts
|
|
@@ -2037,6 +2113,1266 @@ var AugmentImporter = class extends BaseImporter {
|
|
|
2037
2113
|
}
|
|
2038
2114
|
};
|
|
2039
2115
|
|
|
2116
|
+
// src/import/importers/OpencodeImporter.ts
|
|
2117
|
+
import os2 from "os";
|
|
2118
|
+
import path9 from "path";
|
|
2119
|
+
import fse9 from "fs-extra";
|
|
2120
|
+
var OpencodeImporter = class extends BaseImporter {
|
|
2121
|
+
name = "opencode";
|
|
2122
|
+
displayName = "OpenCode";
|
|
2123
|
+
homePath = "~/.config/opencode";
|
|
2124
|
+
get dataHome() {
|
|
2125
|
+
return path9.join(os2.homedir(), ".local", "share", "opencode");
|
|
2126
|
+
}
|
|
2127
|
+
async detect() {
|
|
2128
|
+
if (await fse9.pathExists(this.resolvedHomePath)) return true;
|
|
2129
|
+
if (await fse9.pathExists(this.dataHome)) return true;
|
|
2130
|
+
for (const config of this.globalConfigCandidates()) {
|
|
2131
|
+
if (await fse9.pathExists(config.path)) return true;
|
|
2132
|
+
}
|
|
2133
|
+
return false;
|
|
2134
|
+
}
|
|
2135
|
+
async scan() {
|
|
2136
|
+
const available = /* @__PURE__ */ new Map();
|
|
2137
|
+
if (!await this.detect()) {
|
|
2138
|
+
return { source: this.name, available };
|
|
2139
|
+
}
|
|
2140
|
+
const settings = await this.existingConfigFiles();
|
|
2141
|
+
if (settings.length > 0) {
|
|
2142
|
+
available.set("settings", {
|
|
2143
|
+
count: settings.length,
|
|
2144
|
+
description: "OpenCode config and TUI settings"
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
const mcp = await this.collectMcpServers(settings);
|
|
2148
|
+
if (Object.keys(mcp).length > 0) {
|
|
2149
|
+
available.set("mcp", {
|
|
2150
|
+
count: Object.keys(mcp).length,
|
|
2151
|
+
description: `${Object.keys(mcp).length} OpenCode MCP server${Object.keys(mcp).length !== 1 ? "s" : ""}`
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
if (await fse9.pathExists(path9.join(this.resolvedHomePath, "AGENTS.md"))) {
|
|
2155
|
+
available.set("memory", { count: 1, description: "OpenCode global AGENTS.md rules" });
|
|
2156
|
+
}
|
|
2157
|
+
const skills = await this.discoverSkillDirs();
|
|
2158
|
+
if (skills.length > 0) {
|
|
2159
|
+
available.set("skills", {
|
|
2160
|
+
count: skills.length,
|
|
2161
|
+
description: `${skills.length} OpenCode skill${skills.length !== 1 ? "s" : ""}`
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
const sessionFiles = await this.discoverJsonSessionFiles();
|
|
2165
|
+
const sqlitePath = path9.join(this.dataHome, "opencode.db");
|
|
2166
|
+
const hasSqlite = await fse9.pathExists(sqlitePath);
|
|
2167
|
+
if (sessionFiles.length > 0 || hasSqlite) {
|
|
2168
|
+
available.set("sessions", {
|
|
2169
|
+
count: sessionFiles.length + (hasSqlite ? 1 : 0),
|
|
2170
|
+
description: hasSqlite ? "OpenCode session database and JSON session files" : `${sessionFiles.length} OpenCode JSON session${sessionFiles.length !== 1 ? "s" : ""}`
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
return { source: this.name, available };
|
|
2174
|
+
}
|
|
2175
|
+
async import(categories, onProgress) {
|
|
2176
|
+
const start = Date.now();
|
|
2177
|
+
const imported = /* @__PURE__ */ new Map();
|
|
2178
|
+
const errors = [];
|
|
2179
|
+
for (const category of categories) {
|
|
2180
|
+
switch (category) {
|
|
2181
|
+
case "sessions":
|
|
2182
|
+
await this.importSessions(imported, errors, onProgress);
|
|
2183
|
+
break;
|
|
2184
|
+
case "settings":
|
|
2185
|
+
await this.importSettings(imported, errors, onProgress);
|
|
2186
|
+
break;
|
|
2187
|
+
case "mcp":
|
|
2188
|
+
await this.importMcp(imported, errors, onProgress);
|
|
2189
|
+
break;
|
|
2190
|
+
case "memory":
|
|
2191
|
+
await this.importMemory(imported, errors, onProgress);
|
|
2192
|
+
break;
|
|
2193
|
+
case "skills":
|
|
2194
|
+
await this.importSkills(imported, errors, onProgress);
|
|
2195
|
+
break;
|
|
2196
|
+
default:
|
|
2197
|
+
break;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
return {
|
|
2201
|
+
source: this.name,
|
|
2202
|
+
imported,
|
|
2203
|
+
errors,
|
|
2204
|
+
duration: Date.now() - start
|
|
2205
|
+
};
|
|
2206
|
+
}
|
|
2207
|
+
async importSettings(imported, errors, onProgress) {
|
|
2208
|
+
const files = await this.existingConfigFiles();
|
|
2209
|
+
if (files.length === 0) {
|
|
2210
|
+
imported.set("settings", { success: 0, failed: 0, skipped: 1 });
|
|
2211
|
+
return;
|
|
2212
|
+
}
|
|
2213
|
+
onProgress?.({
|
|
2214
|
+
category: "settings",
|
|
2215
|
+
current: 1,
|
|
2216
|
+
total: 1,
|
|
2217
|
+
item: "OpenCode config files",
|
|
2218
|
+
status: "importing"
|
|
2219
|
+
});
|
|
2220
|
+
try {
|
|
2221
|
+
const importedFiles = [];
|
|
2222
|
+
for (const file of files) {
|
|
2223
|
+
const raw = await fse9.readFile(file.path, "utf-8");
|
|
2224
|
+
const parsed = this.parseJsonc(raw);
|
|
2225
|
+
importedFiles.push({
|
|
2226
|
+
file: file.file,
|
|
2227
|
+
raw,
|
|
2228
|
+
...parsed ? { parsed } : {}
|
|
2229
|
+
});
|
|
2230
|
+
}
|
|
2231
|
+
await fse9.ensureDir(AUTOHAND_PATHS.config);
|
|
2232
|
+
await fse9.writeJson(
|
|
2233
|
+
path9.join(AUTOHAND_PATHS.config, "imported-opencode-settings.json"),
|
|
2234
|
+
{
|
|
2235
|
+
importedFrom: "opencode",
|
|
2236
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2237
|
+
files: importedFiles
|
|
2238
|
+
},
|
|
2239
|
+
{ spaces: 2 }
|
|
2240
|
+
);
|
|
2241
|
+
imported.set("settings", { success: 1, failed: 0, skipped: 0 });
|
|
2242
|
+
onProgress?.({
|
|
2243
|
+
category: "settings",
|
|
2244
|
+
current: 1,
|
|
2245
|
+
total: 1,
|
|
2246
|
+
item: "OpenCode config files",
|
|
2247
|
+
status: "done"
|
|
2248
|
+
});
|
|
2249
|
+
} catch (err) {
|
|
2250
|
+
imported.set("settings", { success: 0, failed: 1, skipped: 0 });
|
|
2251
|
+
errors.push({
|
|
2252
|
+
category: "settings",
|
|
2253
|
+
item: "OpenCode config files",
|
|
2254
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2255
|
+
retriable: false
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
async importMcp(imported, errors, onProgress) {
|
|
2260
|
+
const files = await this.existingConfigFiles();
|
|
2261
|
+
if (files.length === 0) {
|
|
2262
|
+
imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
onProgress?.({
|
|
2266
|
+
category: "mcp",
|
|
2267
|
+
current: 1,
|
|
2268
|
+
total: 1,
|
|
2269
|
+
item: "mcp from opencode config",
|
|
2270
|
+
status: "importing"
|
|
2271
|
+
});
|
|
2272
|
+
try {
|
|
2273
|
+
const mcpServers = await this.collectMcpServers(files);
|
|
2274
|
+
if (Object.keys(mcpServers).length === 0) {
|
|
2275
|
+
imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
|
|
2276
|
+
return;
|
|
2277
|
+
}
|
|
2278
|
+
await fse9.ensureDir(AUTOHAND_PATHS.config);
|
|
2279
|
+
await fse9.writeJson(
|
|
2280
|
+
path9.join(AUTOHAND_PATHS.config, "imported-opencode-mcp.json"),
|
|
2281
|
+
{
|
|
2282
|
+
importedFrom: "opencode",
|
|
2283
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2284
|
+
mcpServers
|
|
2285
|
+
},
|
|
2286
|
+
{ spaces: 2 }
|
|
2287
|
+
);
|
|
2288
|
+
imported.set("mcp", { success: 1, failed: 0, skipped: 0 });
|
|
2289
|
+
onProgress?.({
|
|
2290
|
+
category: "mcp",
|
|
2291
|
+
current: 1,
|
|
2292
|
+
total: 1,
|
|
2293
|
+
item: "mcp from opencode config",
|
|
2294
|
+
status: "done"
|
|
2295
|
+
});
|
|
2296
|
+
} catch (err) {
|
|
2297
|
+
imported.set("mcp", { success: 0, failed: 1, skipped: 0 });
|
|
2298
|
+
errors.push({
|
|
2299
|
+
category: "mcp",
|
|
2300
|
+
item: "mcp from opencode config",
|
|
2301
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2302
|
+
retriable: false
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
async importMemory(imported, errors, onProgress) {
|
|
2307
|
+
const agentsPath = path9.join(this.resolvedHomePath, "AGENTS.md");
|
|
2308
|
+
if (!await fse9.pathExists(agentsPath)) {
|
|
2309
|
+
imported.set("memory", { success: 0, failed: 0, skipped: 1 });
|
|
2310
|
+
return;
|
|
2311
|
+
}
|
|
2312
|
+
onProgress?.({
|
|
2313
|
+
category: "memory",
|
|
2314
|
+
current: 1,
|
|
2315
|
+
total: 1,
|
|
2316
|
+
item: "AGENTS.md",
|
|
2317
|
+
status: "importing"
|
|
2318
|
+
});
|
|
2319
|
+
try {
|
|
2320
|
+
const destDir = path9.join(AUTOHAND_PATHS.memory, "imported-opencode");
|
|
2321
|
+
await fse9.ensureDir(destDir);
|
|
2322
|
+
await fse9.copy(agentsPath, path9.join(destDir, "AGENTS.md"));
|
|
2323
|
+
imported.set("memory", { success: 1, failed: 0, skipped: 0 });
|
|
2324
|
+
onProgress?.({
|
|
2325
|
+
category: "memory",
|
|
2326
|
+
current: 1,
|
|
2327
|
+
total: 1,
|
|
2328
|
+
item: "AGENTS.md",
|
|
2329
|
+
status: "done"
|
|
2330
|
+
});
|
|
2331
|
+
} catch (err) {
|
|
2332
|
+
imported.set("memory", { success: 0, failed: 1, skipped: 0 });
|
|
2333
|
+
errors.push({
|
|
2334
|
+
category: "memory",
|
|
2335
|
+
item: "AGENTS.md",
|
|
2336
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2337
|
+
retriable: true
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
async importSkills(imported, errors, onProgress) {
|
|
2342
|
+
const skills = await this.discoverSkillDirs();
|
|
2343
|
+
if (skills.length === 0) {
|
|
2344
|
+
imported.set("skills", { success: 0, failed: 0, skipped: 1 });
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2347
|
+
const destBase = path9.join(AUTOHAND_PATHS.skills, "imported-opencode");
|
|
2348
|
+
let success = 0;
|
|
2349
|
+
let failed = 0;
|
|
2350
|
+
for (let i = 0; i < skills.length; i++) {
|
|
2351
|
+
const skill = skills[i];
|
|
2352
|
+
onProgress?.({
|
|
2353
|
+
category: "skills",
|
|
2354
|
+
current: i + 1,
|
|
2355
|
+
total: skills.length,
|
|
2356
|
+
item: skill.name,
|
|
2357
|
+
status: "importing"
|
|
2358
|
+
});
|
|
2359
|
+
try {
|
|
2360
|
+
await fse9.ensureDir(destBase);
|
|
2361
|
+
await fse9.copy(skill.path, path9.join(destBase, skill.name));
|
|
2362
|
+
success++;
|
|
2363
|
+
} catch (err) {
|
|
2364
|
+
failed++;
|
|
2365
|
+
errors.push({
|
|
2366
|
+
category: "skills",
|
|
2367
|
+
item: skill.name,
|
|
2368
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2369
|
+
retriable: true
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
imported.set("skills", { success, failed, skipped: 0 });
|
|
2374
|
+
}
|
|
2375
|
+
async importSessions(imported, errors, onProgress) {
|
|
2376
|
+
const jsonSessions = await this.discoverJsonSessionFiles();
|
|
2377
|
+
const sqlitePath = path9.join(this.dataHome, "opencode.db");
|
|
2378
|
+
const hasSqlite = await fse9.pathExists(sqlitePath);
|
|
2379
|
+
if (jsonSessions.length === 0 && !hasSqlite) {
|
|
2380
|
+
imported.set("sessions", { success: 0, failed: 0, skipped: 1 });
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2383
|
+
let success = 0;
|
|
2384
|
+
let failed = 0;
|
|
2385
|
+
let skipped = 0;
|
|
2386
|
+
const skipReasons = {};
|
|
2387
|
+
const trackSkip = (reason) => {
|
|
2388
|
+
skipped++;
|
|
2389
|
+
skipReasons[reason] = (skipReasons[reason] ?? 0) + 1;
|
|
2390
|
+
};
|
|
2391
|
+
const total = jsonSessions.length + (hasSqlite ? 1 : 0);
|
|
2392
|
+
for (let i = 0; i < jsonSessions.length; i++) {
|
|
2393
|
+
const sessionFile = jsonSessions[i];
|
|
2394
|
+
onProgress?.({
|
|
2395
|
+
category: "sessions",
|
|
2396
|
+
current: i + 1,
|
|
2397
|
+
total,
|
|
2398
|
+
item: sessionFile.sessionId,
|
|
2399
|
+
status: "importing"
|
|
2400
|
+
});
|
|
2401
|
+
try {
|
|
2402
|
+
const session = await this.readJsonSession(sessionFile);
|
|
2403
|
+
if (!session || session.messages.length === 0) {
|
|
2404
|
+
trackSkip("no user/assistant messages");
|
|
2405
|
+
continue;
|
|
2406
|
+
}
|
|
2407
|
+
const result = await this.writeAutohandSession({
|
|
2408
|
+
projectPath: session.projectPath,
|
|
2409
|
+
projectName: path9.basename(session.projectPath),
|
|
2410
|
+
model: session.model,
|
|
2411
|
+
messages: session.messages,
|
|
2412
|
+
source: this.name,
|
|
2413
|
+
originalId: session.originalId,
|
|
2414
|
+
createdAt: session.messages[0].timestamp,
|
|
2415
|
+
closedAt: session.messages[session.messages.length - 1].timestamp,
|
|
2416
|
+
summary: session.summary,
|
|
2417
|
+
status: "completed"
|
|
2418
|
+
});
|
|
2419
|
+
if (result === null) {
|
|
2420
|
+
trackSkip("already imported");
|
|
2421
|
+
} else {
|
|
2422
|
+
success++;
|
|
2423
|
+
}
|
|
2424
|
+
} catch (err) {
|
|
2425
|
+
failed++;
|
|
2426
|
+
errors.push({
|
|
2427
|
+
category: "sessions",
|
|
2428
|
+
item: sessionFile.sessionId,
|
|
2429
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2430
|
+
retriable: true
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
if (hasSqlite) {
|
|
2435
|
+
onProgress?.({
|
|
2436
|
+
category: "sessions",
|
|
2437
|
+
current: jsonSessions.length + 1,
|
|
2438
|
+
total,
|
|
2439
|
+
item: "opencode.db",
|
|
2440
|
+
status: "importing"
|
|
2441
|
+
});
|
|
2442
|
+
try {
|
|
2443
|
+
const sqliteResult = await this.importSqliteSessions(sqlitePath);
|
|
2444
|
+
success += sqliteResult.success;
|
|
2445
|
+
failed += sqliteResult.failed;
|
|
2446
|
+
skipped += sqliteResult.skipped;
|
|
2447
|
+
for (const [reason, count] of Object.entries(sqliteResult.skipReasons)) {
|
|
2448
|
+
skipReasons[reason] = (skipReasons[reason] ?? 0) + count;
|
|
2449
|
+
}
|
|
2450
|
+
errors.push(...sqliteResult.errors);
|
|
2451
|
+
} catch (err) {
|
|
2452
|
+
failed++;
|
|
2453
|
+
errors.push({
|
|
2454
|
+
category: "sessions",
|
|
2455
|
+
item: "opencode.db",
|
|
2456
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2457
|
+
retriable: true
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
imported.set("sessions", {
|
|
2462
|
+
success,
|
|
2463
|
+
failed,
|
|
2464
|
+
skipped,
|
|
2465
|
+
...Object.keys(skipReasons).length > 0 ? { skipReasons } : {}
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
async readJsonSession(sessionFile) {
|
|
2469
|
+
const sessionData = this.asRecord(await fse9.readJson(sessionFile.path));
|
|
2470
|
+
const originalId = this.readString(sessionData, "id") ?? sessionFile.sessionId;
|
|
2471
|
+
const projectPath = this.readString(sessionData, "directory") ?? this.readString(this.asRecord(sessionData.path), "cwd") ?? this.readString(this.asRecord(sessionData.path), "root") ?? process.cwd();
|
|
2472
|
+
const model = this.extractModel(sessionData);
|
|
2473
|
+
const summary = this.readString(sessionData, "title") ?? "Imported OpenCode session";
|
|
2474
|
+
const rawMessages = await this.readJsonMessages(originalId);
|
|
2475
|
+
const messages = rawMessages.map((message) => this.convertStoredMessage(message)).filter((message) => message !== null);
|
|
2476
|
+
if (messages.length === 0) return null;
|
|
2477
|
+
return {
|
|
2478
|
+
originalId,
|
|
2479
|
+
projectPath,
|
|
2480
|
+
model,
|
|
2481
|
+
summary,
|
|
2482
|
+
messages
|
|
2483
|
+
};
|
|
2484
|
+
}
|
|
2485
|
+
async readJsonMessages(sessionId) {
|
|
2486
|
+
const messageDirs = [
|
|
2487
|
+
path9.join(this.dataHome, "storage", "message", sessionId),
|
|
2488
|
+
path9.join(this.dataHome, "storage", "session", "message", sessionId)
|
|
2489
|
+
];
|
|
2490
|
+
const messages = [];
|
|
2491
|
+
for (const messageDir of messageDirs) {
|
|
2492
|
+
if (!await fse9.pathExists(messageDir)) continue;
|
|
2493
|
+
const entries = await this.readDir(messageDir);
|
|
2494
|
+
for (const entry of entries.filter((item) => item.isFile() && item.name.endsWith(".json"))) {
|
|
2495
|
+
const messagePath = path9.join(messageDir, entry.name);
|
|
2496
|
+
const messageData = this.asRecord(await fse9.readJson(messagePath));
|
|
2497
|
+
const messageId = this.readString(messageData, "id") ?? path9.basename(entry.name, ".json");
|
|
2498
|
+
const role = this.normalizeRole(
|
|
2499
|
+
this.readString(messageData, "role") ?? this.readString(this.asRecord(messageData.data), "role") ?? this.readString(this.asRecord(messageData.info), "role")
|
|
2500
|
+
);
|
|
2501
|
+
if (!role) continue;
|
|
2502
|
+
const parts = await this.readJsonParts(sessionId, messageId);
|
|
2503
|
+
const content = parts.join("") || this.readString(messageData, "content") || this.readString(this.asRecord(messageData.data), "content") || this.readString(messageData, "text");
|
|
2504
|
+
messages.push({
|
|
2505
|
+
id: messageId,
|
|
2506
|
+
role,
|
|
2507
|
+
timestamp: this.toIsoTimestamp(
|
|
2508
|
+
this.asRecord(messageData.time).created ?? messageData.time_created ?? this.asRecord(messageData.data).time_created
|
|
2509
|
+
),
|
|
2510
|
+
content
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
return messages.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
2515
|
+
}
|
|
2516
|
+
async readJsonParts(sessionId, messageId) {
|
|
2517
|
+
const partDirs = [
|
|
2518
|
+
path9.join(this.dataHome, "storage", "part", messageId),
|
|
2519
|
+
path9.join(this.dataHome, "storage", "session", "part", sessionId, messageId)
|
|
2520
|
+
];
|
|
2521
|
+
const parts = [];
|
|
2522
|
+
for (const partDir of partDirs) {
|
|
2523
|
+
if (!await fse9.pathExists(partDir)) continue;
|
|
2524
|
+
const entries = await this.readDir(partDir);
|
|
2525
|
+
for (const entry of entries.filter((item) => item.isFile() && item.name.endsWith(".json"))) {
|
|
2526
|
+
const partData = this.asRecord(await fse9.readJson(path9.join(partDir, entry.name)));
|
|
2527
|
+
const text = this.extractPartText(partData);
|
|
2528
|
+
if (text) parts.push(text);
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
return parts;
|
|
2532
|
+
}
|
|
2533
|
+
async importSqliteSessions(sqlitePath) {
|
|
2534
|
+
let DatabaseSync;
|
|
2535
|
+
try {
|
|
2536
|
+
({ DatabaseSync } = await import("sqlite"));
|
|
2537
|
+
} catch {
|
|
2538
|
+
return {
|
|
2539
|
+
success: 0,
|
|
2540
|
+
failed: 0,
|
|
2541
|
+
skipped: 1,
|
|
2542
|
+
skipReasons: { "node:sqlite unavailable": 1 },
|
|
2543
|
+
errors: []
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
const db = new DatabaseSync(sqlitePath, { readOnly: true });
|
|
2547
|
+
const errors = [];
|
|
2548
|
+
const skipReasons = {};
|
|
2549
|
+
let success = 0;
|
|
2550
|
+
let failed = 0;
|
|
2551
|
+
let skipped = 0;
|
|
2552
|
+
const trackSkip = (reason) => {
|
|
2553
|
+
skipped++;
|
|
2554
|
+
skipReasons[reason] = (skipReasons[reason] ?? 0) + 1;
|
|
2555
|
+
};
|
|
2556
|
+
try {
|
|
2557
|
+
const sessions = db.prepare(
|
|
2558
|
+
"SELECT id, directory, title, model, time_created, time_updated FROM session ORDER BY time_created ASC"
|
|
2559
|
+
).all();
|
|
2560
|
+
for (const sessionRow of sessions) {
|
|
2561
|
+
const originalId = this.readString(sessionRow, "id");
|
|
2562
|
+
if (!originalId) {
|
|
2563
|
+
trackSkip("missing session id");
|
|
2564
|
+
continue;
|
|
2565
|
+
}
|
|
2566
|
+
try {
|
|
2567
|
+
const messages = this.readSqliteMessages(db, originalId);
|
|
2568
|
+
if (messages.length === 0) {
|
|
2569
|
+
trackSkip("no user/assistant messages");
|
|
2570
|
+
continue;
|
|
2571
|
+
}
|
|
2572
|
+
const projectPath = this.readString(sessionRow, "directory") ?? process.cwd();
|
|
2573
|
+
const result = await this.writeAutohandSession({
|
|
2574
|
+
projectPath,
|
|
2575
|
+
projectName: path9.basename(projectPath),
|
|
2576
|
+
model: this.extractModel(sessionRow),
|
|
2577
|
+
messages,
|
|
2578
|
+
source: this.name,
|
|
2579
|
+
originalId,
|
|
2580
|
+
createdAt: messages[0].timestamp,
|
|
2581
|
+
closedAt: messages[messages.length - 1].timestamp,
|
|
2582
|
+
summary: this.readString(sessionRow, "title") ?? this.buildSummary(messages),
|
|
2583
|
+
status: "completed"
|
|
2584
|
+
});
|
|
2585
|
+
if (result === null) {
|
|
2586
|
+
trackSkip("already imported");
|
|
2587
|
+
} else {
|
|
2588
|
+
success++;
|
|
2589
|
+
}
|
|
2590
|
+
} catch (err) {
|
|
2591
|
+
failed++;
|
|
2592
|
+
errors.push({
|
|
2593
|
+
category: "sessions",
|
|
2594
|
+
item: originalId,
|
|
2595
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2596
|
+
retriable: true
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
} finally {
|
|
2601
|
+
db.close();
|
|
2602
|
+
}
|
|
2603
|
+
return { success, failed, skipped, skipReasons, errors };
|
|
2604
|
+
}
|
|
2605
|
+
readSqliteMessages(db, sessionId) {
|
|
2606
|
+
const messages = db.prepare(
|
|
2607
|
+
"SELECT id, data, time_created FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC"
|
|
2608
|
+
).all(sessionId);
|
|
2609
|
+
const converted = [];
|
|
2610
|
+
for (const messageRow of messages) {
|
|
2611
|
+
const data = this.parseStoredJson(messageRow.data);
|
|
2612
|
+
const role = this.normalizeRole(this.readString(data, "role"));
|
|
2613
|
+
if (!role) continue;
|
|
2614
|
+
const messageId = this.readString(messageRow, "id");
|
|
2615
|
+
if (!messageId) continue;
|
|
2616
|
+
const parts = db.prepare(
|
|
2617
|
+
"SELECT data FROM part WHERE message_id = ? ORDER BY time_created ASC, id ASC"
|
|
2618
|
+
).all(messageId);
|
|
2619
|
+
const content = parts.map((part) => this.extractPartText(this.parseStoredJson(part.data))).filter(Boolean).join("") || this.readString(data, "content") || this.readString(data, "text") || "";
|
|
2620
|
+
if (!content.trim()) continue;
|
|
2621
|
+
converted.push({
|
|
2622
|
+
role,
|
|
2623
|
+
content,
|
|
2624
|
+
timestamp: this.toIsoTimestamp(messageRow.time_created)
|
|
2625
|
+
});
|
|
2626
|
+
}
|
|
2627
|
+
return converted;
|
|
2628
|
+
}
|
|
2629
|
+
async discoverJsonSessionFiles() {
|
|
2630
|
+
const sessionRoot = path9.join(this.dataHome, "storage", "session");
|
|
2631
|
+
if (!await fse9.pathExists(sessionRoot)) return [];
|
|
2632
|
+
const projectDirs = await this.readDir(sessionRoot);
|
|
2633
|
+
const files = [];
|
|
2634
|
+
for (const projectDir of projectDirs.filter((entry) => entry.isDirectory())) {
|
|
2635
|
+
if (projectDir.name === "message" || projectDir.name === "part" || projectDir.name === "info") {
|
|
2636
|
+
continue;
|
|
2637
|
+
}
|
|
2638
|
+
const dir = path9.join(sessionRoot, projectDir.name);
|
|
2639
|
+
const entries = await this.readDir(dir);
|
|
2640
|
+
for (const entry of entries.filter((item) => item.isFile() && item.name.endsWith(".json"))) {
|
|
2641
|
+
files.push({
|
|
2642
|
+
path: path9.join(dir, entry.name),
|
|
2643
|
+
projectId: projectDir.name,
|
|
2644
|
+
sessionId: path9.basename(entry.name, ".json")
|
|
2645
|
+
});
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
return files;
|
|
2649
|
+
}
|
|
2650
|
+
async existingConfigFiles() {
|
|
2651
|
+
const existing = [];
|
|
2652
|
+
for (const candidate of this.globalConfigCandidates()) {
|
|
2653
|
+
if (await fse9.pathExists(candidate.path)) {
|
|
2654
|
+
existing.push(candidate);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
return existing;
|
|
2658
|
+
}
|
|
2659
|
+
globalConfigCandidates() {
|
|
2660
|
+
return [
|
|
2661
|
+
{ path: path9.join(this.resolvedHomePath, "opencode.json"), file: "opencode.json" },
|
|
2662
|
+
{ path: path9.join(this.resolvedHomePath, "opencode.jsonc"), file: "opencode.jsonc" },
|
|
2663
|
+
{ path: path9.join(this.resolvedHomePath, "tui.json"), file: "tui.json" },
|
|
2664
|
+
{ path: path9.join(this.resolvedHomePath, "tui.jsonc"), file: "tui.jsonc" },
|
|
2665
|
+
{ path: path9.join(this.dataHome, "opencode.json"), file: "legacy-data/opencode.json" },
|
|
2666
|
+
{ path: path9.join(this.dataHome, "opencode.jsonc"), file: "legacy-data/opencode.jsonc" },
|
|
2667
|
+
{ path: path9.join(os2.homedir(), ".opencode.json"), file: "~/.opencode.json" },
|
|
2668
|
+
{ path: path9.join(os2.homedir(), ".opencode.jsonc"), file: "~/.opencode.jsonc" }
|
|
2669
|
+
];
|
|
2670
|
+
}
|
|
2671
|
+
async discoverSkillDirs() {
|
|
2672
|
+
const skillsDir = path9.join(this.resolvedHomePath, "skills");
|
|
2673
|
+
if (!await fse9.pathExists(skillsDir)) return [];
|
|
2674
|
+
const entries = await this.readDir(skillsDir);
|
|
2675
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
2676
|
+
name: entry.name,
|
|
2677
|
+
path: path9.join(skillsDir, entry.name)
|
|
2678
|
+
}));
|
|
2679
|
+
}
|
|
2680
|
+
async collectMcpServers(files) {
|
|
2681
|
+
const combined = {};
|
|
2682
|
+
for (const file of files) {
|
|
2683
|
+
try {
|
|
2684
|
+
const raw = await fse9.readFile(file.path, "utf-8");
|
|
2685
|
+
const parsed = this.parseJsonc(raw);
|
|
2686
|
+
const mcp = parsed ? this.asRecord(parsed.mcp) : {};
|
|
2687
|
+
Object.assign(combined, mcp);
|
|
2688
|
+
} catch {
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
return combined;
|
|
2692
|
+
}
|
|
2693
|
+
parseJsonc(content) {
|
|
2694
|
+
try {
|
|
2695
|
+
return this.asRecord(JSON.parse(this.removeTrailingCommas(this.stripJsonComments(content))));
|
|
2696
|
+
} catch {
|
|
2697
|
+
return void 0;
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
stripJsonComments(content) {
|
|
2701
|
+
let output = "";
|
|
2702
|
+
let inString = false;
|
|
2703
|
+
let escaped = false;
|
|
2704
|
+
for (let i = 0; i < content.length; i++) {
|
|
2705
|
+
const char = content[i];
|
|
2706
|
+
const next = content[i + 1];
|
|
2707
|
+
if (inString) {
|
|
2708
|
+
output += char;
|
|
2709
|
+
if (escaped) {
|
|
2710
|
+
escaped = false;
|
|
2711
|
+
} else if (char === "\\") {
|
|
2712
|
+
escaped = true;
|
|
2713
|
+
} else if (char === '"') {
|
|
2714
|
+
inString = false;
|
|
2715
|
+
}
|
|
2716
|
+
continue;
|
|
2717
|
+
}
|
|
2718
|
+
if (char === '"') {
|
|
2719
|
+
inString = true;
|
|
2720
|
+
output += char;
|
|
2721
|
+
continue;
|
|
2722
|
+
}
|
|
2723
|
+
if (char === "/" && next === "/") {
|
|
2724
|
+
while (i < content.length && content[i] !== "\n") i++;
|
|
2725
|
+
output += "\n";
|
|
2726
|
+
continue;
|
|
2727
|
+
}
|
|
2728
|
+
if (char === "/" && next === "*") {
|
|
2729
|
+
i += 2;
|
|
2730
|
+
while (i < content.length && !(content[i] === "*" && content[i + 1] === "/")) i++;
|
|
2731
|
+
i++;
|
|
2732
|
+
continue;
|
|
2733
|
+
}
|
|
2734
|
+
output += char;
|
|
2735
|
+
}
|
|
2736
|
+
return output;
|
|
2737
|
+
}
|
|
2738
|
+
removeTrailingCommas(content) {
|
|
2739
|
+
return content.replace(/,\s*([}\]])/g, "$1");
|
|
2740
|
+
}
|
|
2741
|
+
async readDir(dir) {
|
|
2742
|
+
return await fse9.readdir(dir, { withFileTypes: true });
|
|
2743
|
+
}
|
|
2744
|
+
convertStoredMessage(message) {
|
|
2745
|
+
if (!message.content?.trim()) return null;
|
|
2746
|
+
return {
|
|
2747
|
+
role: message.role,
|
|
2748
|
+
content: message.content,
|
|
2749
|
+
timestamp: message.timestamp
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
normalizeRole(role) {
|
|
2753
|
+
if (role === "user" || role === "assistant" || role === "tool" || role === "system") {
|
|
2754
|
+
return role;
|
|
2755
|
+
}
|
|
2756
|
+
return null;
|
|
2757
|
+
}
|
|
2758
|
+
extractPartText(part) {
|
|
2759
|
+
const type = this.readString(part, "type");
|
|
2760
|
+
if (type && !["text", "reasoning"].includes(type)) return "";
|
|
2761
|
+
const text = this.readString(part, "text") ?? this.readString(this.asRecord(part.data), "text");
|
|
2762
|
+
return text ?? "";
|
|
2763
|
+
}
|
|
2764
|
+
extractModel(record) {
|
|
2765
|
+
const direct = this.readString(record, "model");
|
|
2766
|
+
if (direct) return direct;
|
|
2767
|
+
const model = this.parseStoredJson(record.model);
|
|
2768
|
+
const providerId = this.readString(model, "providerID") ?? this.readString(model, "provider_id");
|
|
2769
|
+
const modelId = this.readString(model, "id") ?? this.readString(model, "model");
|
|
2770
|
+
if (providerId && modelId) return `${providerId}/${modelId}`;
|
|
2771
|
+
if (modelId) return modelId;
|
|
2772
|
+
return "opencode";
|
|
2773
|
+
}
|
|
2774
|
+
parseStoredJson(value) {
|
|
2775
|
+
if (typeof value === "string") {
|
|
2776
|
+
try {
|
|
2777
|
+
return this.asRecord(JSON.parse(value));
|
|
2778
|
+
} catch {
|
|
2779
|
+
return {};
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
return this.asRecord(value);
|
|
2783
|
+
}
|
|
2784
|
+
toIsoTimestamp(value) {
|
|
2785
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2786
|
+
const milliseconds = value > 1e10 ? value : value * 1e3;
|
|
2787
|
+
return new Date(milliseconds).toISOString();
|
|
2788
|
+
}
|
|
2789
|
+
if (typeof value === "string" && value.trim()) {
|
|
2790
|
+
const time = Date.parse(value);
|
|
2791
|
+
return Number.isNaN(time) ? (/* @__PURE__ */ new Date()).toISOString() : new Date(time).toISOString();
|
|
2792
|
+
}
|
|
2793
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2794
|
+
}
|
|
2795
|
+
buildSummary(messages) {
|
|
2796
|
+
const firstUser = messages.find((message) => message.role === "user");
|
|
2797
|
+
if (!firstUser) return "Imported OpenCode session";
|
|
2798
|
+
const text = firstUser.content.trim().slice(0, 100);
|
|
2799
|
+
return text.length < firstUser.content.trim().length ? `${text}...` : text;
|
|
2800
|
+
}
|
|
2801
|
+
readString(record, key) {
|
|
2802
|
+
const obj = this.asRecord(record);
|
|
2803
|
+
const value = obj[key];
|
|
2804
|
+
return typeof value === "string" ? value : void 0;
|
|
2805
|
+
}
|
|
2806
|
+
asRecord(value) {
|
|
2807
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
2808
|
+
return value;
|
|
2809
|
+
}
|
|
2810
|
+
return {};
|
|
2811
|
+
}
|
|
2812
|
+
};
|
|
2813
|
+
|
|
2814
|
+
// src/import/importers/KimiImporter.ts
|
|
2815
|
+
import path10 from "path";
|
|
2816
|
+
import fse10 from "fs-extra";
|
|
2817
|
+
var KimiImporter = class extends BaseImporter {
|
|
2818
|
+
name = "kimi";
|
|
2819
|
+
displayName = "Kimi CLI";
|
|
2820
|
+
homePath = "~/.kimi";
|
|
2821
|
+
async scan() {
|
|
2822
|
+
const available = /* @__PURE__ */ new Map();
|
|
2823
|
+
const home = this.resolvedHomePath;
|
|
2824
|
+
if (!await fse10.pathExists(home)) {
|
|
2825
|
+
return { source: this.name, available };
|
|
2826
|
+
}
|
|
2827
|
+
const configPath = path10.join(home, "config.toml");
|
|
2828
|
+
const metadataPath = path10.join(home, "kimi.json");
|
|
2829
|
+
const settingsCount = await this.countExisting([configPath, metadataPath]);
|
|
2830
|
+
if (settingsCount > 0) {
|
|
2831
|
+
available.set("settings", {
|
|
2832
|
+
count: settingsCount,
|
|
2833
|
+
description: "Kimi config.toml and runtime metadata"
|
|
2834
|
+
});
|
|
2835
|
+
}
|
|
2836
|
+
if (await fse10.pathExists(path10.join(home, "mcp.json"))) {
|
|
2837
|
+
available.set("mcp", { count: 1, description: "Kimi MCP server configuration" });
|
|
2838
|
+
}
|
|
2839
|
+
if (await fse10.pathExists(path10.join(home, "AGENTS.md"))) {
|
|
2840
|
+
available.set("memory", { count: 1, description: "Kimi global AGENTS.md instructions" });
|
|
2841
|
+
}
|
|
2842
|
+
const skills = await this.discoverSkillDirs();
|
|
2843
|
+
if (skills.length > 0) {
|
|
2844
|
+
available.set("skills", {
|
|
2845
|
+
count: skills.length,
|
|
2846
|
+
description: `${skills.length} Kimi skill${skills.length !== 1 ? "s" : ""}`
|
|
2847
|
+
});
|
|
2848
|
+
}
|
|
2849
|
+
const sessions = await this.discoverSessionDirs();
|
|
2850
|
+
if (sessions.length > 0) {
|
|
2851
|
+
available.set("sessions", {
|
|
2852
|
+
count: sessions.length,
|
|
2853
|
+
description: `${sessions.length} Kimi session${sessions.length !== 1 ? "s" : ""}`
|
|
2854
|
+
});
|
|
2855
|
+
}
|
|
2856
|
+
if (await fse10.pathExists(configPath)) {
|
|
2857
|
+
try {
|
|
2858
|
+
const config = await fse10.readFile(configPath, "utf-8");
|
|
2859
|
+
const hooks = this.extractTomlArraySections(config, "hooks");
|
|
2860
|
+
if (hooks.length > 0) {
|
|
2861
|
+
available.set("hooks", {
|
|
2862
|
+
count: hooks.length,
|
|
2863
|
+
description: `${hooks.length} Kimi hook${hooks.length !== 1 ? "s" : ""}`
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
} catch {
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
return { source: this.name, available };
|
|
2870
|
+
}
|
|
2871
|
+
async import(categories, onProgress) {
|
|
2872
|
+
const start = Date.now();
|
|
2873
|
+
const imported = /* @__PURE__ */ new Map();
|
|
2874
|
+
const errors = [];
|
|
2875
|
+
for (const category of categories) {
|
|
2876
|
+
switch (category) {
|
|
2877
|
+
case "sessions":
|
|
2878
|
+
await this.importSessions(imported, errors, onProgress);
|
|
2879
|
+
break;
|
|
2880
|
+
case "settings":
|
|
2881
|
+
await this.importSettings(imported, errors, onProgress);
|
|
2882
|
+
break;
|
|
2883
|
+
case "mcp":
|
|
2884
|
+
await this.importMcp(imported, errors, onProgress);
|
|
2885
|
+
break;
|
|
2886
|
+
case "memory":
|
|
2887
|
+
await this.importMemory(imported, errors, onProgress);
|
|
2888
|
+
break;
|
|
2889
|
+
case "skills":
|
|
2890
|
+
await this.importSkills(imported, errors, onProgress);
|
|
2891
|
+
break;
|
|
2892
|
+
case "hooks":
|
|
2893
|
+
await this.importHooks(imported, errors, onProgress);
|
|
2894
|
+
break;
|
|
2895
|
+
default:
|
|
2896
|
+
break;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
return {
|
|
2900
|
+
source: this.name,
|
|
2901
|
+
imported,
|
|
2902
|
+
errors,
|
|
2903
|
+
duration: Date.now() - start
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2906
|
+
async importSettings(imported, errors, onProgress) {
|
|
2907
|
+
const configPath = path10.join(this.resolvedHomePath, "config.toml");
|
|
2908
|
+
const metadataPath = path10.join(this.resolvedHomePath, "kimi.json");
|
|
2909
|
+
const hasConfig = await fse10.pathExists(configPath);
|
|
2910
|
+
const hasMetadata = await fse10.pathExists(metadataPath);
|
|
2911
|
+
if (!hasConfig && !hasMetadata) {
|
|
2912
|
+
imported.set("settings", { success: 0, failed: 0, skipped: 1 });
|
|
2913
|
+
return;
|
|
2914
|
+
}
|
|
2915
|
+
onProgress?.({
|
|
2916
|
+
category: "settings",
|
|
2917
|
+
current: 1,
|
|
2918
|
+
total: 1,
|
|
2919
|
+
item: "config.toml / kimi.json",
|
|
2920
|
+
status: "importing"
|
|
2921
|
+
});
|
|
2922
|
+
try {
|
|
2923
|
+
const output = {
|
|
2924
|
+
importedFrom: "kimi",
|
|
2925
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2926
|
+
};
|
|
2927
|
+
if (hasConfig) {
|
|
2928
|
+
const raw = await fse10.readFile(configPath, "utf-8");
|
|
2929
|
+
output.configToml = raw;
|
|
2930
|
+
output.parsed = this.parseToml(raw);
|
|
2931
|
+
}
|
|
2932
|
+
if (hasMetadata) {
|
|
2933
|
+
output.metadata = await this.safeReadJson(metadataPath);
|
|
2934
|
+
}
|
|
2935
|
+
await fse10.ensureDir(AUTOHAND_PATHS.config);
|
|
2936
|
+
await fse10.writeJson(path10.join(AUTOHAND_PATHS.config, "imported-kimi-settings.json"), output, {
|
|
2937
|
+
spaces: 2
|
|
2938
|
+
});
|
|
2939
|
+
imported.set("settings", { success: 1, failed: 0, skipped: 0 });
|
|
2940
|
+
onProgress?.({
|
|
2941
|
+
category: "settings",
|
|
2942
|
+
current: 1,
|
|
2943
|
+
total: 1,
|
|
2944
|
+
item: "config.toml / kimi.json",
|
|
2945
|
+
status: "done"
|
|
2946
|
+
});
|
|
2947
|
+
} catch (err) {
|
|
2948
|
+
imported.set("settings", { success: 0, failed: 1, skipped: 0 });
|
|
2949
|
+
errors.push({
|
|
2950
|
+
category: "settings",
|
|
2951
|
+
item: "config.toml / kimi.json",
|
|
2952
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2953
|
+
retriable: false
|
|
2954
|
+
});
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
async importMcp(imported, errors, onProgress) {
|
|
2958
|
+
const mcpPath = path10.join(this.resolvedHomePath, "mcp.json");
|
|
2959
|
+
if (!await fse10.pathExists(mcpPath)) {
|
|
2960
|
+
imported.set("mcp", { success: 0, failed: 0, skipped: 1 });
|
|
2961
|
+
return;
|
|
2962
|
+
}
|
|
2963
|
+
onProgress?.({
|
|
2964
|
+
category: "mcp",
|
|
2965
|
+
current: 1,
|
|
2966
|
+
total: 1,
|
|
2967
|
+
item: "mcp.json",
|
|
2968
|
+
status: "importing"
|
|
2969
|
+
});
|
|
2970
|
+
try {
|
|
2971
|
+
const mcpData = await this.safeReadJson(mcpPath);
|
|
2972
|
+
await fse10.ensureDir(AUTOHAND_PATHS.config);
|
|
2973
|
+
await fse10.writeJson(
|
|
2974
|
+
path10.join(AUTOHAND_PATHS.config, "imported-kimi-mcp.json"),
|
|
2975
|
+
{
|
|
2976
|
+
importedFrom: "kimi",
|
|
2977
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2978
|
+
mcpServers: this.extractMcpServers(mcpData) ?? mcpData
|
|
2979
|
+
},
|
|
2980
|
+
{ spaces: 2 }
|
|
2981
|
+
);
|
|
2982
|
+
imported.set("mcp", { success: 1, failed: 0, skipped: 0 });
|
|
2983
|
+
onProgress?.({
|
|
2984
|
+
category: "mcp",
|
|
2985
|
+
current: 1,
|
|
2986
|
+
total: 1,
|
|
2987
|
+
item: "mcp.json",
|
|
2988
|
+
status: "done"
|
|
2989
|
+
});
|
|
2990
|
+
} catch (err) {
|
|
2991
|
+
imported.set("mcp", { success: 0, failed: 1, skipped: 0 });
|
|
2992
|
+
errors.push({
|
|
2993
|
+
category: "mcp",
|
|
2994
|
+
item: "mcp.json",
|
|
2995
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2996
|
+
retriable: false
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
async importMemory(imported, errors, onProgress) {
|
|
3001
|
+
const agentsPath = path10.join(this.resolvedHomePath, "AGENTS.md");
|
|
3002
|
+
if (!await fse10.pathExists(agentsPath)) {
|
|
3003
|
+
imported.set("memory", { success: 0, failed: 0, skipped: 1 });
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
onProgress?.({
|
|
3007
|
+
category: "memory",
|
|
3008
|
+
current: 1,
|
|
3009
|
+
total: 1,
|
|
3010
|
+
item: "AGENTS.md",
|
|
3011
|
+
status: "importing"
|
|
3012
|
+
});
|
|
3013
|
+
try {
|
|
3014
|
+
const destDir = path10.join(AUTOHAND_PATHS.memory, "imported-kimi");
|
|
3015
|
+
await fse10.ensureDir(destDir);
|
|
3016
|
+
await fse10.copy(agentsPath, path10.join(destDir, "AGENTS.md"));
|
|
3017
|
+
imported.set("memory", { success: 1, failed: 0, skipped: 0 });
|
|
3018
|
+
onProgress?.({
|
|
3019
|
+
category: "memory",
|
|
3020
|
+
current: 1,
|
|
3021
|
+
total: 1,
|
|
3022
|
+
item: "AGENTS.md",
|
|
3023
|
+
status: "done"
|
|
3024
|
+
});
|
|
3025
|
+
} catch (err) {
|
|
3026
|
+
imported.set("memory", { success: 0, failed: 1, skipped: 0 });
|
|
3027
|
+
errors.push({
|
|
3028
|
+
category: "memory",
|
|
3029
|
+
item: "AGENTS.md",
|
|
3030
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3031
|
+
retriable: true
|
|
3032
|
+
});
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
async importSkills(imported, errors, onProgress) {
|
|
3036
|
+
const skills = await this.discoverSkillDirs();
|
|
3037
|
+
if (skills.length === 0) {
|
|
3038
|
+
imported.set("skills", { success: 0, failed: 0, skipped: 1 });
|
|
3039
|
+
return;
|
|
3040
|
+
}
|
|
3041
|
+
const destBase = path10.join(AUTOHAND_PATHS.skills, "imported-kimi");
|
|
3042
|
+
let success = 0;
|
|
3043
|
+
let failed = 0;
|
|
3044
|
+
for (let i = 0; i < skills.length; i++) {
|
|
3045
|
+
const skill = skills[i];
|
|
3046
|
+
onProgress?.({
|
|
3047
|
+
category: "skills",
|
|
3048
|
+
current: i + 1,
|
|
3049
|
+
total: skills.length,
|
|
3050
|
+
item: skill.name,
|
|
3051
|
+
status: "importing"
|
|
3052
|
+
});
|
|
3053
|
+
try {
|
|
3054
|
+
await fse10.ensureDir(destBase);
|
|
3055
|
+
await fse10.copy(skill.path, path10.join(destBase, skill.name));
|
|
3056
|
+
success++;
|
|
3057
|
+
} catch (err) {
|
|
3058
|
+
failed++;
|
|
3059
|
+
errors.push({
|
|
3060
|
+
category: "skills",
|
|
3061
|
+
item: skill.name,
|
|
3062
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3063
|
+
retriable: true
|
|
3064
|
+
});
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
imported.set("skills", { success, failed, skipped: 0 });
|
|
3068
|
+
}
|
|
3069
|
+
async importHooks(imported, errors, onProgress) {
|
|
3070
|
+
const configPath = path10.join(this.resolvedHomePath, "config.toml");
|
|
3071
|
+
if (!await fse10.pathExists(configPath)) {
|
|
3072
|
+
imported.set("hooks", { success: 0, failed: 0, skipped: 1 });
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
onProgress?.({
|
|
3076
|
+
category: "hooks",
|
|
3077
|
+
current: 1,
|
|
3078
|
+
total: 1,
|
|
3079
|
+
item: "hooks from config.toml",
|
|
3080
|
+
status: "importing"
|
|
3081
|
+
});
|
|
3082
|
+
try {
|
|
3083
|
+
const config = await fse10.readFile(configPath, "utf-8");
|
|
3084
|
+
const hooks = this.extractTomlArraySections(config, "hooks");
|
|
3085
|
+
if (hooks.length === 0) {
|
|
3086
|
+
imported.set("hooks", { success: 0, failed: 0, skipped: 1 });
|
|
3087
|
+
return;
|
|
3088
|
+
}
|
|
3089
|
+
await fse10.ensureDir(AUTOHAND_PATHS.config);
|
|
3090
|
+
await fse10.writeJson(
|
|
3091
|
+
path10.join(AUTOHAND_PATHS.config, "imported-kimi-hooks.json"),
|
|
3092
|
+
{
|
|
3093
|
+
importedFrom: "kimi",
|
|
3094
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3095
|
+
hooksToml: hooks.join("\n\n")
|
|
3096
|
+
},
|
|
3097
|
+
{ spaces: 2 }
|
|
3098
|
+
);
|
|
3099
|
+
imported.set("hooks", { success: 1, failed: 0, skipped: 0 });
|
|
3100
|
+
onProgress?.({
|
|
3101
|
+
category: "hooks",
|
|
3102
|
+
current: 1,
|
|
3103
|
+
total: 1,
|
|
3104
|
+
item: "hooks from config.toml",
|
|
3105
|
+
status: "done"
|
|
3106
|
+
});
|
|
3107
|
+
} catch (err) {
|
|
3108
|
+
imported.set("hooks", { success: 0, failed: 1, skipped: 0 });
|
|
3109
|
+
errors.push({
|
|
3110
|
+
category: "hooks",
|
|
3111
|
+
item: "hooks from config.toml",
|
|
3112
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3113
|
+
retriable: false
|
|
3114
|
+
});
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
async importSessions(imported, errors, onProgress) {
|
|
3118
|
+
const sessions = await this.discoverSessionDirs();
|
|
3119
|
+
if (sessions.length === 0) {
|
|
3120
|
+
imported.set("sessions", { success: 0, failed: 0, skipped: 1 });
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
let success = 0;
|
|
3124
|
+
let failed = 0;
|
|
3125
|
+
let skipped = 0;
|
|
3126
|
+
const skipReasons = {};
|
|
3127
|
+
const trackSkip = (reason) => {
|
|
3128
|
+
skipped++;
|
|
3129
|
+
skipReasons[reason] = (skipReasons[reason] ?? 0) + 1;
|
|
3130
|
+
};
|
|
3131
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
3132
|
+
const session = sessions[i];
|
|
3133
|
+
onProgress?.({
|
|
3134
|
+
category: "sessions",
|
|
3135
|
+
current: i + 1,
|
|
3136
|
+
total: sessions.length,
|
|
3137
|
+
item: session.sessionId,
|
|
3138
|
+
status: "importing"
|
|
3139
|
+
});
|
|
3140
|
+
try {
|
|
3141
|
+
const importedSession = await this.readKimiSession(session);
|
|
3142
|
+
if (!importedSession || importedSession.messages.length === 0) {
|
|
3143
|
+
trackSkip("no user/assistant messages");
|
|
3144
|
+
continue;
|
|
3145
|
+
}
|
|
3146
|
+
const result = await this.writeAutohandSession({
|
|
3147
|
+
projectPath: importedSession.projectPath,
|
|
3148
|
+
projectName: path10.basename(importedSession.projectPath),
|
|
3149
|
+
model: importedSession.model,
|
|
3150
|
+
messages: importedSession.messages,
|
|
3151
|
+
source: this.name,
|
|
3152
|
+
originalId: session.sessionId,
|
|
3153
|
+
createdAt: importedSession.messages[0].timestamp,
|
|
3154
|
+
closedAt: importedSession.messages[importedSession.messages.length - 1].timestamp,
|
|
3155
|
+
summary: importedSession.summary,
|
|
3156
|
+
status: "completed"
|
|
3157
|
+
});
|
|
3158
|
+
if (result === null) {
|
|
3159
|
+
trackSkip("already imported");
|
|
3160
|
+
} else {
|
|
3161
|
+
success++;
|
|
3162
|
+
}
|
|
3163
|
+
} catch (err) {
|
|
3164
|
+
failed++;
|
|
3165
|
+
errors.push({
|
|
3166
|
+
category: "sessions",
|
|
3167
|
+
item: session.sessionId,
|
|
3168
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3169
|
+
retriable: true
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
imported.set("sessions", {
|
|
3174
|
+
success,
|
|
3175
|
+
failed,
|
|
3176
|
+
skipped,
|
|
3177
|
+
...Object.keys(skipReasons).length > 0 ? { skipReasons } : {}
|
|
3178
|
+
});
|
|
3179
|
+
}
|
|
3180
|
+
async readKimiSession(session) {
|
|
3181
|
+
const contextPath = path10.join(session.dir, "context.jsonl");
|
|
3182
|
+
const records = await this.readJsonlFile(contextPath);
|
|
3183
|
+
const state = await this.readOptionalJson(path10.join(session.dir, "state.json"));
|
|
3184
|
+
const config = await this.readOptionalConfig();
|
|
3185
|
+
const messages = [];
|
|
3186
|
+
for (const record of records) {
|
|
3187
|
+
const role = this.normalizeRole(this.readString(record, "role"));
|
|
3188
|
+
if (!role) continue;
|
|
3189
|
+
const content = this.extractMessageContent(record.content ?? record.message);
|
|
3190
|
+
if (!content.trim()) continue;
|
|
3191
|
+
messages.push({
|
|
3192
|
+
role,
|
|
3193
|
+
content,
|
|
3194
|
+
timestamp: this.toIsoTimestamp(record.timestamp ?? record.time ?? record.created_at)
|
|
3195
|
+
});
|
|
3196
|
+
}
|
|
3197
|
+
if (messages.length === 0) return null;
|
|
3198
|
+
const projectPath = this.readString(state, "cwd") ?? this.readString(state, "work_dir") ?? this.readString(state, "workDir") ?? this.readString(state, "directory") ?? this.readString(state, "projectPath") ?? process.cwd();
|
|
3199
|
+
const title = this.readString(state, "title");
|
|
3200
|
+
const model = this.readString(state, "model") ?? this.readString(config, "default_model") ?? "kimi";
|
|
3201
|
+
return {
|
|
3202
|
+
projectPath,
|
|
3203
|
+
model,
|
|
3204
|
+
summary: title?.trim() || this.buildSummary(messages),
|
|
3205
|
+
messages
|
|
3206
|
+
};
|
|
3207
|
+
}
|
|
3208
|
+
async discoverSessionDirs() {
|
|
3209
|
+
const sessionsDir = path10.join(this.resolvedHomePath, "sessions");
|
|
3210
|
+
if (!await fse10.pathExists(sessionsDir)) return [];
|
|
3211
|
+
const workDirs = await this.readDir(sessionsDir);
|
|
3212
|
+
const sessions = [];
|
|
3213
|
+
for (const workDir of workDirs.filter((entry) => entry.isDirectory())) {
|
|
3214
|
+
const workDirPath = path10.join(sessionsDir, workDir.name);
|
|
3215
|
+
const sessionDirs = await this.readDir(workDirPath);
|
|
3216
|
+
for (const sessionDir of sessionDirs.filter((entry) => entry.isDirectory())) {
|
|
3217
|
+
const dir = path10.join(workDirPath, sessionDir.name);
|
|
3218
|
+
if (await fse10.pathExists(path10.join(dir, "context.jsonl"))) {
|
|
3219
|
+
sessions.push({ dir, workDirHash: workDir.name, sessionId: sessionDir.name });
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
return sessions;
|
|
3224
|
+
}
|
|
3225
|
+
async discoverSkillDirs() {
|
|
3226
|
+
const skillsDir = path10.join(this.resolvedHomePath, "skills");
|
|
3227
|
+
if (!await fse10.pathExists(skillsDir)) return [];
|
|
3228
|
+
const entries = await this.readDir(skillsDir);
|
|
3229
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
3230
|
+
name: entry.name,
|
|
3231
|
+
path: path10.join(skillsDir, entry.name)
|
|
3232
|
+
}));
|
|
3233
|
+
}
|
|
3234
|
+
async readDir(dir) {
|
|
3235
|
+
return await fse10.readdir(dir, { withFileTypes: true });
|
|
3236
|
+
}
|
|
3237
|
+
async countExisting(paths) {
|
|
3238
|
+
let count = 0;
|
|
3239
|
+
for (const candidate of paths) {
|
|
3240
|
+
if (await fse10.pathExists(candidate)) count++;
|
|
3241
|
+
}
|
|
3242
|
+
return count;
|
|
3243
|
+
}
|
|
3244
|
+
async readOptionalJson(filePath) {
|
|
3245
|
+
if (!await fse10.pathExists(filePath)) return {};
|
|
3246
|
+
try {
|
|
3247
|
+
const json = await fse10.readJson(filePath);
|
|
3248
|
+
return this.asRecord(json);
|
|
3249
|
+
} catch {
|
|
3250
|
+
return {};
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
async readOptionalConfig() {
|
|
3254
|
+
const configPath = path10.join(this.resolvedHomePath, "config.toml");
|
|
3255
|
+
if (!await fse10.pathExists(configPath)) return {};
|
|
3256
|
+
try {
|
|
3257
|
+
const raw = await fse10.readFile(configPath, "utf-8");
|
|
3258
|
+
return this.parseToml(raw);
|
|
3259
|
+
} catch {
|
|
3260
|
+
return {};
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
parseToml(content) {
|
|
3264
|
+
const result = {};
|
|
3265
|
+
let currentSection = "";
|
|
3266
|
+
for (const rawLine of content.split("\n")) {
|
|
3267
|
+
const line = rawLine.trim();
|
|
3268
|
+
if (!line || line.startsWith("#") || line.startsWith("[[")) continue;
|
|
3269
|
+
const sectionMatch = line.match(/^\[([^\]]+)\]$/);
|
|
3270
|
+
if (sectionMatch) {
|
|
3271
|
+
currentSection = sectionMatch[1];
|
|
3272
|
+
continue;
|
|
3273
|
+
}
|
|
3274
|
+
const kvMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)\s*=\s*(.+)$/);
|
|
3275
|
+
if (!kvMatch) continue;
|
|
3276
|
+
const key = currentSection ? `${currentSection}.${kvMatch[1]}` : kvMatch[1];
|
|
3277
|
+
let value = kvMatch[2].trim();
|
|
3278
|
+
const inlineComment = value.indexOf(" #");
|
|
3279
|
+
if (inlineComment > 0) {
|
|
3280
|
+
value = value.slice(0, inlineComment).trim();
|
|
3281
|
+
}
|
|
3282
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
3283
|
+
result[key] = value.slice(1, -1);
|
|
3284
|
+
} else if (value === "true") {
|
|
3285
|
+
result[key] = true;
|
|
3286
|
+
} else if (value === "false") {
|
|
3287
|
+
result[key] = false;
|
|
3288
|
+
} else if (/^-?\d+(\.\d+)?$/.test(value)) {
|
|
3289
|
+
result[key] = Number(value);
|
|
3290
|
+
} else {
|
|
3291
|
+
result[key] = value;
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
return result;
|
|
3295
|
+
}
|
|
3296
|
+
extractTomlArraySections(content, sectionName) {
|
|
3297
|
+
const header = `[[${sectionName}]]`;
|
|
3298
|
+
const blocks = [];
|
|
3299
|
+
let current = null;
|
|
3300
|
+
for (const rawLine of content.split("\n")) {
|
|
3301
|
+
const line = rawLine.trim();
|
|
3302
|
+
if (line === header) {
|
|
3303
|
+
if (current && current.length > 0) blocks.push(current.join("\n").trim());
|
|
3304
|
+
current = [rawLine];
|
|
3305
|
+
continue;
|
|
3306
|
+
}
|
|
3307
|
+
if (current) {
|
|
3308
|
+
if (line.startsWith("[[") && line !== header) {
|
|
3309
|
+
blocks.push(current.join("\n").trim());
|
|
3310
|
+
current = null;
|
|
3311
|
+
} else {
|
|
3312
|
+
current.push(rawLine);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
if (current && current.length > 0) blocks.push(current.join("\n").trim());
|
|
3317
|
+
return blocks.filter((block) => block.length > 0);
|
|
3318
|
+
}
|
|
3319
|
+
extractMcpServers(data) {
|
|
3320
|
+
const direct = data.mcpServers;
|
|
3321
|
+
if (direct && typeof direct === "object" && !Array.isArray(direct)) {
|
|
3322
|
+
return direct;
|
|
3323
|
+
}
|
|
3324
|
+
return void 0;
|
|
3325
|
+
}
|
|
3326
|
+
normalizeRole(role) {
|
|
3327
|
+
if (!role || role.startsWith("_")) return null;
|
|
3328
|
+
if (role === "model") return "assistant";
|
|
3329
|
+
if (role === "user" || role === "assistant" || role === "tool" || role === "system") {
|
|
3330
|
+
return role;
|
|
3331
|
+
}
|
|
3332
|
+
return null;
|
|
3333
|
+
}
|
|
3334
|
+
extractMessageContent(content) {
|
|
3335
|
+
if (typeof content === "string") return content;
|
|
3336
|
+
if (Array.isArray(content)) {
|
|
3337
|
+
return content.map((item) => this.extractMessageContent(item)).filter(Boolean).join("");
|
|
3338
|
+
}
|
|
3339
|
+
const record = this.asRecord(content);
|
|
3340
|
+
if (record) {
|
|
3341
|
+
const text = this.readString(record, "text") ?? this.readString(record, "content");
|
|
3342
|
+
if (text) return text;
|
|
3343
|
+
}
|
|
3344
|
+
return "";
|
|
3345
|
+
}
|
|
3346
|
+
toIsoTimestamp(value) {
|
|
3347
|
+
if (typeof value === "string" && value.trim()) {
|
|
3348
|
+
const time = Date.parse(value);
|
|
3349
|
+
return Number.isNaN(time) ? (/* @__PURE__ */ new Date()).toISOString() : new Date(time).toISOString();
|
|
3350
|
+
}
|
|
3351
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
3352
|
+
const milliseconds = value > 1e10 ? value : value * 1e3;
|
|
3353
|
+
return new Date(milliseconds).toISOString();
|
|
3354
|
+
}
|
|
3355
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3356
|
+
}
|
|
3357
|
+
buildSummary(messages) {
|
|
3358
|
+
const firstUser = messages.find((message) => message.role === "user");
|
|
3359
|
+
if (!firstUser) return "Imported Kimi session";
|
|
3360
|
+
const text = firstUser.content.trim().slice(0, 100);
|
|
3361
|
+
return text.length < firstUser.content.trim().length ? `${text}...` : text;
|
|
3362
|
+
}
|
|
3363
|
+
readString(record, key) {
|
|
3364
|
+
const obj = this.asRecord(record);
|
|
3365
|
+
const value = obj?.[key];
|
|
3366
|
+
return typeof value === "string" ? value : void 0;
|
|
3367
|
+
}
|
|
3368
|
+
asRecord(value) {
|
|
3369
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
3370
|
+
return value;
|
|
3371
|
+
}
|
|
3372
|
+
return {};
|
|
3373
|
+
}
|
|
3374
|
+
};
|
|
3375
|
+
|
|
2040
3376
|
// src/import/registry.ts
|
|
2041
3377
|
var ImporterRegistry = class {
|
|
2042
3378
|
importers;
|
|
@@ -2049,6 +3385,8 @@ var ImporterRegistry = class {
|
|
|
2049
3385
|
this.register(new ClineImporter());
|
|
2050
3386
|
this.register(new ContinueImporter());
|
|
2051
3387
|
this.register(new AugmentImporter());
|
|
3388
|
+
this.register(new OpencodeImporter());
|
|
3389
|
+
this.register(new KimiImporter());
|
|
2052
3390
|
}
|
|
2053
3391
|
/**
|
|
2054
3392
|
* Register an importer instance by its source name.
|