autohand-cli 0.8.3 → 0.9.1
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 +191 -74
- package/dist/{AgentRegistry-ODDXPAFR.js → AgentRegistry-GOV7FN2O.js} +2 -2
- package/dist/AgentRegistry-J2C6JBZ3.cjs +10 -0
- package/dist/{AutomodeManager-EOVHGRPP.js → AutomodeManager-APLLPEYJ.js} +31 -17
- package/dist/{AutomodeManager-6ATBE7Q5.cjs → AutomodeManager-MPSXT2RH.cjs} +38 -24
- package/dist/CommunitySkillsCache-22BB3J6H.cjs +8 -0
- package/dist/{CommunitySkillsCache-QLE57BN5.js → CommunitySkillsCache-ZACDPD4J.js} +2 -2
- package/dist/GitHubRegistryFetcher-CYJLF2XL.cjs +7 -0
- package/dist/{GitHubRegistryFetcher-NT5GFZXS.js → GitHubRegistryFetcher-J2BWPXJF.js} +1 -1
- package/dist/{HookManager-B2F35M27.js → HookManager-2S6AHOC3.js} +1 -1
- package/dist/{HookManager-PFAFE3FK.cjs → HookManager-TVEQI5ZU.cjs} +2 -2
- package/dist/{ImportWizard-OHRKBANZ.js → ImportWizard-AEBMAKXE.js} +33 -9
- package/dist/{ImportWizard-CJRZPPHL.cjs → ImportWizard-AF2XL6DS.cjs} +37 -13
- package/dist/LearnAdvisor-KKEQ5QCV.js +9 -0
- package/dist/LearnAdvisor-Q7RAYLPF.cjs +9 -0
- package/dist/{McpClientManager-NQ3EW2IF.cjs → McpClientManager-BNSKLHIN.cjs} +2 -2
- package/dist/{McpClientManager-VBIMGKXU.js → McpClientManager-SL35BR24.js} +1 -1
- package/dist/MemoryManager-PMNAEZMB.cjs +8 -0
- package/dist/{MemoryManager-2LAT7IHS.js → MemoryManager-QZRLTUB5.js} +2 -2
- package/dist/NVIDIAProvider-C3FWQOBZ.cjs +14 -0
- package/dist/NVIDIAProvider-SJPY3ONR.js +14 -0
- package/dist/{PermissionManager-7NQHRCHY.js → PermissionManager-MT7KBNNR.js} +3 -3
- package/dist/PermissionManager-URCNP5EC.cjs +11 -0
- package/dist/{ProjectProfiler-UG42W6WD.cjs → ProjectProfiler-CDAE7ECW.cjs} +1 -0
- package/dist/{ProjectProfiler-P4QJQWWA.js → ProjectProfiler-NZTJDRHD.js} +1 -0
- package/dist/ProviderFactory-56N3ECE4.cjs +12 -0
- package/dist/{ProviderFactory-2IYJ5OPW.js → ProviderFactory-RB4RVAF6.js} +4 -1
- package/dist/SessionManager-2IZGWASQ.cjs +10 -0
- package/dist/{SessionManager-4U4JFQ3C.js → SessionManager-554PHVPC.js} +2 -2
- package/dist/SkillsRegistry-GMRVONOQ.cjs +9 -0
- package/dist/{SkillsRegistry-RFEINXRT.js → SkillsRegistry-NHHMIUYJ.js} +2 -2
- package/dist/SubAgent-4GOR2FIJ.js +13 -0
- package/dist/SubAgent-ZJMDH4FI.cjs +13 -0
- package/dist/{SyncApiClient-B5RT2ECG.js → SyncApiClient-G3FM65IV.js} +1 -1
- package/dist/SyncApiClient-ODBDECOG.cjs +11 -0
- package/dist/about-3USFSGOH.js +15 -0
- package/dist/about-QR52U5DD.cjs +15 -0
- package/dist/acp-5Y2W6OZP.js +1556 -0
- package/dist/acp-GSYE75OB.cjs +1556 -0
- package/dist/actionExecutor-KHUU3Z3Q.cjs +28 -0
- package/dist/actionExecutor-PLQJZLZV.js +28 -0
- package/dist/add-dir-BTAD5OZS.cjs +11 -0
- package/dist/{add-dir-TUJM3PG5.js → add-dir-HCERJDBR.js} +3 -2
- package/dist/agent-B3EVT7NN.cjs +126 -0
- package/dist/agent-SATQ3WZ3.js +126 -0
- package/dist/agents/builtin/code-cleaner.md +1 -1
- package/dist/agents/builtin/docs-writer.md +1 -1
- package/dist/agents/builtin/researcher.md +2 -2
- package/dist/agents/builtin/reviewer.md +1 -1
- package/dist/agents/builtin/tester.md +1 -1
- package/dist/agents/builtin/todo-resolver.md +1 -1
- package/dist/agents-44CRJGM7.cjs +18 -0
- package/dist/agents-NN4ZAJ7R.js +18 -0
- package/dist/agents-new-6D6G4QS6.cjs +17 -0
- package/dist/agents-new-7GAQ25EK.js +17 -0
- package/dist/{autoSkill-LQEVQFIH.js → autoSkill-66PKCYTW.js} +2 -2
- package/dist/autoSkill-VQLGBELN.cjs +20 -0
- package/dist/automode-45DWV4TN.cjs +10 -0
- package/dist/{automode-R6P3VHLS.js → automode-BUF3VGXU.js} +2 -2
- package/dist/browserToolBridge-BXRQB4B4.cjs +58 -0
- package/dist/browserToolBridge-F5N66PE7.js +58 -0
- package/dist/chrome-Q2U73HZB.cjs +50 -0
- package/dist/chrome-Q54OALOK.cjs +21 -0
- package/dist/chrome-Y3T7EIHG.js +50 -0
- package/dist/chrome-ZNJ46OYW.js +21 -0
- package/dist/chromeSkill-53TH55PM.js +105 -0
- package/dist/chromeSkill-THW7N4IY.cjs +105 -0
- package/dist/{chunk-HXGBSJL5.cjs → chunk-22SCR3EV.cjs} +2 -2
- package/dist/chunk-26G7YGOW.js +367 -0
- package/dist/{chunk-3L53OA4E.cjs → chunk-2ESQR35E.cjs} +10 -10
- package/dist/chunk-2H5O745H.js +63 -0
- package/dist/{chunk-ULDM2SNB.js → chunk-2IW5YFJ4.js} +48 -47
- package/dist/{chunk-U55TWFJI.cjs → chunk-2VHB43IX.cjs} +24 -6
- package/dist/chunk-3EDDDZS2.cjs +5 -0
- package/dist/{chunk-X5VSP65C.cjs → chunk-3ICORF7M.cjs} +4 -4
- package/dist/chunk-3OF56EMA.cjs +197 -0
- package/dist/chunk-3UC6DMFI.cjs +93 -0
- package/dist/{chunk-64H4FRM3.cjs → chunk-3UHRCHKB.cjs} +32 -34
- package/dist/{chunk-JCLYQ2JC.js → chunk-3ZOOH44N.js} +12 -6
- package/dist/{chunk-TUD3Z3BD.js → chunk-44ZWOBTI.js} +136 -55
- package/dist/chunk-4567QNRB.js +444 -0
- package/dist/chunk-45CHNQM6.cjs +517 -0
- package/dist/chunk-46MTALKD.js +44 -0
- package/dist/{chunk-WHE2SWHU.js → chunk-4E7SHPNQ.js} +2 -2
- package/dist/chunk-4LMUDS2K.js +124 -0
- package/dist/{chunk-W7RYQJLO.cjs → chunk-4XFHP2SN.cjs} +46 -15
- package/dist/chunk-4XVLNOFA.js +360 -0
- package/dist/{chunk-GBHDROGL.js → chunk-575PXZX7.js} +16 -4
- package/dist/chunk-5A7ZL64N.js +139 -0
- package/dist/chunk-5GCQ5UMV.cjs +85 -0
- package/dist/chunk-5JTTM5SC.js +59 -0
- package/dist/{chunk-IETRBBMP.cjs → chunk-5K3CDSWZ.cjs} +108 -31
- package/dist/{chunk-KLWJIPU2.cjs → chunk-5SFV2NCY.cjs} +20 -16
- package/dist/chunk-5ZNYX4VH.cjs +71 -0
- package/dist/{chunk-A4IJHHV7.cjs → chunk-63ANVAOJ.cjs} +52 -11
- package/dist/{chunk-MYISNQH4.js → chunk-65LRPW5W.js} +1 -1
- package/dist/chunk-6AYJCDTA.js +360 -0
- package/dist/{chunk-X2MSVKDV.js → chunk-6HF6XSCC.js} +2 -2
- package/dist/{chunk-AEJH23FO.cjs → chunk-6JWCGQJU.cjs} +6 -6
- package/dist/chunk-6OECOAK5.cjs +360 -0
- package/dist/chunk-6R25D2H5.js +121 -0
- package/dist/chunk-7DJJGKM6.js +77 -0
- package/dist/{chunk-VG34MG2U.js → chunk-7IRQ7JEH.js} +9 -6
- package/dist/chunk-7MY4JHER.js +27 -0
- package/dist/chunk-7PJKTSRN.js +152 -0
- package/dist/{chunk-SKYG33B2.cjs → chunk-7PT646AL.cjs} +3 -3
- package/dist/chunk-7WAUCLLQ.js +229 -0
- package/dist/{chunk-U46VYPLR.cjs → chunk-7XTUL7ZD.cjs} +9 -9
- package/dist/chunk-AE2ILW25.cjs +152 -0
- package/dist/{chunk-T2M64VHA.cjs → chunk-AOKXYGBQ.cjs} +61 -41
- package/dist/chunk-AQ5PVHOC.cjs +113 -0
- package/dist/{chunk-N2BLVUPM.cjs → chunk-AZ47LKD5.cjs} +3 -3
- package/dist/chunk-B4HSNOIH.cjs +354 -0
- package/dist/chunk-B76FJKEJ.cjs +184 -0
- package/dist/chunk-BP37FVBM.js +85 -0
- package/dist/chunk-BQU3HAE7.js +21 -0
- package/dist/chunk-BYE7RQFZ.cjs +121 -0
- package/dist/chunk-C46B72VK.js +1034 -0
- package/dist/{chunk-HIVRCQS2.js → chunk-C5QIQQ37.js} +56 -25
- package/dist/chunk-CCIDL4SA.js +19931 -0
- package/dist/{chunk-XVUHNWMX.js → chunk-CECH6QQP.js} +17 -19
- package/dist/chunk-CFAWTLSC.js +13 -0
- package/dist/{chunk-ZYQMLKOK.cjs → chunk-CK4HAHVY.cjs} +212 -70
- package/dist/chunk-CO2AADYU.cjs +360 -0
- package/dist/chunk-CRTCZ4WL.cjs +19931 -0
- package/dist/chunk-CSTUTDTH.js +75 -0
- package/dist/{chunk-K2C56QGS.cjs → chunk-D546G7DA.cjs} +1650 -479
- package/dist/{chunk-CNBKZEX5.cjs → chunk-DA7NBAJK.cjs} +49 -17
- package/dist/{chunk-G4CAKI3V.js → chunk-DGBPWODD.js} +7 -2
- package/dist/chunk-DHUQZ53B.cjs +29 -0
- package/dist/{chunk-RGR6ME5J.cjs → chunk-DI57A4BX.cjs} +25 -28
- package/dist/{chunk-5K6NGAVM.js → chunk-DNSD7DVJ.js} +67 -52
- package/dist/{chunk-RDF37HKB.cjs → chunk-DSSCERHI.cjs} +3 -2
- package/dist/{chunk-NAJ4IZKD.cjs → chunk-EA2MS25U.cjs} +8 -6
- package/dist/{chunk-SJAVBCOA.js → chunk-EEHWALXA.js} +94 -3
- package/dist/chunk-ES2HJQ4N.js +37 -0
- package/dist/{chunk-G27PQQFD.js → chunk-EYHKL4QC.js} +1 -1
- package/dist/{chunk-SV2WA57F.js → chunk-FBQJZKFX.js} +38 -15
- package/dist/chunk-FFBDRUO5.cjs +59 -0
- package/dist/{chunk-N7LI55V4.js → chunk-FFHSCM5M.js} +15 -8
- package/dist/{chunk-SAHBLB3E.js → chunk-FP46B4X3.js} +208 -3
- package/dist/chunk-FQVG6ZHF.js +197 -0
- package/dist/{chunk-J2GSFVUV.cjs → chunk-GAOPJ5S3.cjs} +74 -59
- package/dist/{chunk-S52YW5ZQ.js → chunk-GNBBIAMD.js} +16 -19
- package/dist/chunk-GSDV75A5.js +715 -0
- package/dist/chunk-GWY26SUD.cjs +63 -0
- package/dist/{chunk-TUAITHWL.js → chunk-H426KOGY.js} +2 -1
- package/dist/{chunk-EZMINVLU.js → chunk-H4D2Q2AL.js} +5 -2
- package/dist/chunk-HC2Q6A3E.cjs +4967 -0
- package/dist/{chunk-3WVJEL7K.cjs → chunk-HDK2EHVH.cjs} +3 -1
- package/dist/{chunk-5IXII4HX.cjs → chunk-HG3ZASBH.cjs} +23 -16
- package/dist/chunk-HK5A54AV.cjs +280 -0
- package/dist/{chunk-LQGVEP3E.js → chunk-HQUSEWT4.js} +45 -13
- package/dist/chunk-HSWWM6AM.js +2340 -0
- package/dist/chunk-HTU4W3GB.js +183 -0
- package/dist/{chunk-HLHTG5ZU.cjs → chunk-HVCIB4SW.cjs} +14 -12
- package/dist/chunk-HXHE2KAO.js +385 -0
- package/dist/{chunk-LJFUXC56.cjs → chunk-HXQREVTA.cjs} +9 -6
- package/dist/{chunk-SLQAYV3W.js → chunk-HZWU6IO3.js} +11 -2
- package/dist/chunk-I2ZK3AOD.js +866 -0
- package/dist/chunk-IEPLQ47J.js +719 -0
- package/dist/chunk-J5HE6CUM.cjs +124 -0
- package/dist/{chunk-LIEXWM2M.js → chunk-JAQO6XDB.js} +19 -1
- package/dist/chunk-JB3JCYBJ.js +113 -0
- package/dist/chunk-JCUHCH37.cjs +247 -0
- package/dist/{chunk-FPHU2ES6.cjs → chunk-JM3ZTQUK.cjs} +19 -9
- package/dist/{chunk-NDMIPTV4.js → chunk-JMJRFSNJ.js} +8 -3
- package/dist/{chunk-ZLSGXMGQ.js → chunk-JMN3GZU6.js} +2 -0
- package/dist/chunk-JPFRI4L4.js +4967 -0
- package/dist/{chunk-BVKXEQVG.cjs → chunk-JV5HVCHU.cjs} +22 -10
- package/dist/chunk-KA2U6MY2.js +388 -0
- package/dist/{chunk-SEKD5FH3.cjs → chunk-KASXKDF2.cjs} +8 -3
- package/dist/chunk-KJ26T7GM.cjs +367 -0
- package/dist/chunk-KM7R5YPS.cjs +385 -0
- package/dist/{chunk-MBBY4ZIK.js → chunk-KMP6Y3LJ.js} +4 -1
- package/dist/chunk-KWXGDSYT.js +184 -0
- package/dist/{chunk-C5IJIM2V.cjs → chunk-L46OUKW5.cjs} +68 -37
- package/dist/{chunk-6UJMCWRY.js → chunk-L6OH44HL.js} +19 -9
- package/dist/chunk-LANGD5CO.js +280 -0
- package/dist/{chunk-APIXPPMT.js → chunk-LEZEWKPA.js} +1004 -39
- package/dist/{chunk-ULQ6MDSJ.cjs → chunk-LFDPTJYF.cjs} +43 -35
- package/dist/chunk-LJD7KR3L.cjs +44 -0
- package/dist/{chunk-NCC6ETZS.js → chunk-LUMV3DB2.js} +41 -33
- package/dist/{chunk-QXH5RCFI.js → chunk-M5DK524Z.js} +2 -2
- package/dist/chunk-M7B7RRBK.cjs +1034 -0
- package/dist/chunk-MANJ67D3.js +3897 -0
- package/dist/{chunk-HPHJ73GU.cjs → chunk-MGNXABSU.cjs} +9 -9
- package/dist/{chunk-6ZCULLCA.js → chunk-MMKZSJUN.js} +1 -1
- package/dist/{chunk-DVUHHH3B.cjs → chunk-MQQH4XQH.cjs} +4 -4
- package/dist/chunk-MUNUUFU7.cjs +21 -0
- package/dist/{chunk-DVZOENQ7.cjs → chunk-MZN6JBRZ.cjs} +9 -4
- package/dist/{chunk-OOKY3HPZ.js → chunk-NB6M6ESM.js} +50 -9
- package/dist/{chunk-BYONM7UM.js → chunk-NBGOIFKP.js} +265 -18
- package/dist/chunk-NHWHEW7M.cjs +75 -0
- package/dist/chunk-NQZH5CR2.cjs +468 -0
- package/dist/{chunk-EGPXJERY.cjs → chunk-NV6LCD2I.cjs} +119 -28
- package/dist/chunk-NVATU4V6.cjs +44 -0
- package/dist/{chunk-YZXUDM5X.js → chunk-NZ3ZWLUW.js} +204 -62
- package/dist/chunk-NZ7GCK7Y.cjs +92 -0
- package/dist/{chunk-VEKDGU2Q.cjs → chunk-NZQFKXM3.cjs} +49 -25
- package/dist/chunk-O5GI6SR3.js +59 -0
- package/dist/{chunk-56SWIDEL.cjs → chunk-OCATAKXV.cjs} +57 -56
- package/dist/{chunk-SKV2F3NM.js → chunk-OIGYWOL6.js} +1 -1
- package/dist/{chunk-IFFXSTOM.cjs → chunk-ONVYXTUT.cjs} +3 -3
- package/dist/chunk-OR67YXQK.cjs +13 -0
- package/dist/chunk-OV3T5MUH.cjs +715 -0
- package/dist/{chunk-OHUZKDGX.js → chunk-P4FUTSVK.js} +3 -3
- package/dist/chunk-P6SLT2F4.cjs +139 -0
- package/dist/{chunk-TNZRZQ7Q.js → chunk-PB7W7R72.js} +3 -78
- package/dist/chunk-PCM3N3CL.cjs +37 -0
- package/dist/{chunk-2AA5MFES.js → chunk-PGFLPURU.js} +8 -5
- package/dist/{chunk-DJDE4DTT.cjs → chunk-PIXQ2AVM.cjs} +25 -19
- package/dist/chunk-PNIAIOMZ.cjs +229 -0
- package/dist/{chunk-HTLINWX6.cjs → chunk-PQBYFEBL.cjs} +16 -13
- package/dist/{chunk-22D2CNTP.cjs → chunk-PSAH4ZQB.cjs} +5 -2
- package/dist/{chunk-3VTAFAL2.js → chunk-PTTZI4QZ.js} +16 -12
- package/dist/{chunk-WPVWQSL7.cjs → chunk-PY73W5MQ.cjs} +16 -13
- package/dist/{chunk-EGMZDTSL.js → chunk-PZZMIYII.js} +10 -2
- package/dist/{chunk-HBZU3RBZ.js → chunk-Q3BS6FPM.js} +34 -10
- package/dist/chunk-QBYGMMDD.js +517 -0
- package/dist/chunk-QLZOMZO5.cjs +388 -0
- package/dist/{chunk-ADUFCS4Q.cjs → chunk-QQ64HEHP.cjs} +160 -79
- package/dist/{chunk-L3TWPROA.js → chunk-QRQF3556.js} +44 -24
- package/dist/{chunk-YHD6TUIR.cjs → chunk-QW2RW2GY.cjs} +2 -0
- package/dist/chunk-RAKO7UN7.js +114 -0
- package/dist/{chunk-7TQH3CL4.cjs → chunk-RBXBH6EB.cjs} +78 -35
- package/dist/chunk-RFUKZIJF.cjs +78 -0
- package/dist/chunk-RS2E32YB.js +71 -0
- package/dist/{chunk-OLSBBZW6.cjs → chunk-S5JNQIGL.cjs} +5 -5
- package/dist/{chunk-FTYY5JJD.js → chunk-S5QKRA2V.js} +2 -2
- package/dist/chunk-SD3NTC7D.cjs +77 -0
- package/dist/{chunk-KPELYZ6L.js → chunk-SDLY4X3G.js} +2 -2
- package/dist/{chunk-IDFF5J2E.js → chunk-SFFEKZGC.js} +38 -7
- package/dist/{chunk-EGFT4PGW.js → chunk-SHRLFX6F.js} +8 -3
- package/dist/{chunk-3WICOC33.js → chunk-SNDDZG5H.js} +124 -84
- package/dist/{chunk-CZXGCVTR.cjs → chunk-SOVR7S3T.cjs} +2 -2
- package/dist/chunk-SPQ7QIQ6.js +78 -0
- package/dist/{chunk-XRZEUWKF.js → chunk-SRMGWMQO.js} +1 -1
- package/dist/{chunk-R33VKSH5.cjs → chunk-SVVP4UUZ.cjs} +11 -11
- package/dist/{chunk-7BTSG4ME.cjs → chunk-SY2P3Z5W.cjs} +1004 -39
- package/dist/chunk-SZD45IDG.js +468 -0
- package/dist/{chunk-3O3MOK5C.cjs → chunk-TE4SYTWR.cjs} +1114 -142
- package/dist/chunk-TH26BQJG.js +101 -0
- package/dist/{chunk-QNGEW5TC.js → chunk-TR6NECEZ.js} +1 -1
- package/dist/{chunk-YGN4CQIP.js → chunk-TYBPTKFT.js} +1 -1
- package/dist/{chunk-GJH7XMSK.js → chunk-U2QUMKCB.js} +8 -6
- package/dist/{chunk-47CKWKEX.cjs → chunk-U6PLSPMD.cjs} +9 -4
- package/dist/chunk-UOQECODR.js +34 -0
- package/dist/chunk-UR27UDTB.js +354 -0
- package/dist/chunk-UWZ4G3SQ.js +93 -0
- package/dist/{chunk-Y72HH2TF.cjs → chunk-V3SZLWEQ.cjs} +33 -24
- package/dist/chunk-V4HGZSKQ.cjs +183 -0
- package/dist/{chunk-3PDTTAKJ.js → chunk-V5ELP2XE.js} +19 -12
- package/dist/{chunk-3K2ESU53.cjs → chunk-VKOXFT4L.cjs} +2 -2
- package/dist/{chunk-XTB6VJVQ.cjs → chunk-VLGGMQUN.cjs} +6 -6
- package/dist/chunk-VQHSYAPZ.cjs +3897 -0
- package/dist/chunk-VUGOOGHB.js +400 -0
- package/dist/chunk-W5QLA6WP.cjs +866 -0
- package/dist/chunk-WBU4Q4GS.cjs +400 -0
- package/dist/{chunk-KWXVKLQ5.cjs → chunk-WGNMOVMT.cjs} +7 -82
- package/dist/chunk-WJYFLQ7G.cjs +27 -0
- package/dist/{chunk-RKJTGGMU.cjs → chunk-WKRDBCP2.cjs} +221 -16
- package/dist/{chunk-ZSPXQYG2.js → chunk-WNJXIACY.js} +7 -5
- package/dist/{chunk-AYS2ASM7.js → chunk-WPE2XHVX.js} +1 -1
- package/dist/chunk-WTB7AFL6.cjs +101 -0
- package/dist/{chunk-JYTDYJVW.js → chunk-X3TI5TJJ.js} +1 -1
- package/dist/chunk-X5P6QQOB.cjs +719 -0
- package/dist/{chunk-245KJE5Y.cjs → chunk-X7XMITIL.cjs} +14 -6
- package/dist/chunk-XF2WIKHR.cjs +34 -0
- package/dist/{chunk-DV2ZHK7B.cjs → chunk-XNIMSVS6.cjs} +49 -26
- package/dist/chunk-XW3XCK4E.cjs +59 -0
- package/dist/{chunk-N23UAW4I.js → chunk-XZVDYC5U.js} +7 -2
- package/dist/chunk-Y5BDE24P.cjs +444 -0
- package/dist/{chunk-NAGQ2PDC.js → chunk-YC5OBZQU.js} +1604 -433
- package/dist/chunk-YISPVAXO.cjs +2340 -0
- package/dist/{chunk-KQGPTCQJ.js → chunk-YQDI753V.js} +68 -25
- package/dist/{chunk-UJ2JSM6H.js → chunk-YVQI26H4.js} +2 -0
- package/dist/{chunk-NNPAM4HC.cjs → chunk-YWH55BWK.cjs} +15 -6
- package/dist/{chunk-X2YOZQIP.cjs → chunk-YWTIXHU6.cjs} +266 -19
- package/dist/{chunk-XX2ZO7DS.js → chunk-YXM6SA7P.js} +25 -16
- package/dist/chunk-YZWE7XSM.js +5 -0
- package/dist/chunk-ZASDSY7P.cjs +114 -0
- package/dist/{chunk-2UC22DJU.js → chunk-ZNGRLCFQ.js} +30 -4
- package/dist/{chunk-KANW6OYC.cjs → chunk-ZNYZB7XY.cjs} +34 -8
- package/dist/{chunk-NA6WQDYW.js → chunk-ZPLCAXJW.js} +1088 -116
- package/dist/{chunk-7UOUW76C.js → chunk-ZQAT5VT5.js} +101 -24
- package/dist/chunk-ZUYYHKQA.js +44 -0
- package/dist/clear-QJXU25IF.cjs +12 -0
- package/dist/{clear-A3N4GK2S.js → clear-Y5TO3RZA.js} +3 -3
- package/dist/communityInstaller-LXMVKVAV.cjs +22 -0
- package/dist/{communityInstaller-LOP2EDH5.js → communityInstaller-RVL4STPS.js} +8 -5
- package/dist/completion-JX4T2ONW.cjs +17 -0
- package/dist/completion-SE3XYG74.js +17 -0
- package/dist/config-3224PRW4.cjs +21 -0
- package/dist/{config-HPJPKTO6.js → config-7KPHKFTP.js} +7 -4
- package/dist/{constants-LISJW3DD.js → constants-EJFAWJQI.js} +1 -1
- package/dist/constants-MCCGUU5F.cjs +21 -0
- package/dist/{defaultHooks-IHSJR2AX.cjs → defaultHooks-2V2CQL63.cjs} +25 -10
- package/dist/{defaultHooks-KUKHK3AG.js → defaultHooks-TMHDU3FS.js} +25 -10
- package/dist/export-BJVIDZC4.js +15 -0
- package/dist/export-KU4557HK.cjs +15 -0
- package/dist/feature-K3LG5IJP.cjs +14 -0
- package/dist/feature-V4JF5TNJ.js +14 -0
- package/dist/features-5OJTLKS7.js +23 -0
- package/dist/features-VCBJQXCX.cjs +23 -0
- package/dist/feedback-D4437VE4.js +18 -0
- package/dist/feedback-VZPEHGFY.cjs +18 -0
- package/dist/fffSearchProvider-2YCNKOYD.js +412 -0
- package/dist/fffSearchProvider-W6627E2V.cjs +412 -0
- package/dist/{filesystem-Z7BWAWMZ.js → filesystem-L6DQKGWK.js} +3 -2
- package/dist/filesystem-PGUPCMVK.cjs +11 -0
- package/dist/go-X4E6BCD6.js +12 -0
- package/dist/go-XREVFS5I.cjs +12 -0
- package/dist/goal-4M3J6JS2.cjs +16 -0
- package/dist/goal-EI66BV7W.js +16 -0
- package/dist/help-GGFS7WHY.cjs +12 -0
- package/dist/{help-GFQXNZOK.js → help-MLIROWKM.js} +2 -2
- package/dist/{history-E3N6BJP7.js → history-GQJ6RZD6.js} +2 -2
- package/dist/history-J4LUIOSI.cjs +14 -0
- package/dist/hooks-FSRIUS6A.cjs +18 -0
- package/dist/hooks-PPFHCF7T.js +18 -0
- package/dist/i18n-CI6VFXL5.cjs +33 -0
- package/dist/{i18n-SY7QRM22.js → i18n-Q7UZJRPL.js} +1 -1
- package/dist/ide-BUSVE54P.js +15 -0
- package/dist/ide-YR27BPGM.cjs +15 -0
- package/dist/immediateCommandRouter-MTEHZXQX.js +15 -0
- package/dist/immediateCommandRouter-ROXU3MWT.cjs +15 -0
- package/dist/{import-W7SVLSTC.js → import-3VBKI6BN.js} +3 -3
- package/dist/{import-ADI37ZUR.cjs → import-C7S6UJMW.cjs} +3 -3
- package/dist/import-DBK4OCDF.cjs +10 -0
- package/dist/{import-KGKKZ3B7.js → import-U47DXCA7.js} +2 -2
- package/dist/index.cjs +837 -23011
- package/dist/index.d.cts +95 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +864 -23038
- package/dist/init-OXTYS72D.cjs +10 -0
- package/dist/{init-7MFK626E.js → init-Q2O4R42R.js} +2 -2
- package/dist/inkMode-VUE6ZDLD.cjs +7 -0
- package/dist/inkMode-WBNFOSAT.js +7 -0
- package/dist/inputPrompt-3CFZDUBH.js +90 -0
- package/dist/inputPrompt-JMACL4EB.cjs +90 -0
- package/dist/language-EK3M6UBV.cjs +22 -0
- package/dist/language-Q3RUGGOW.js +22 -0
- package/dist/learn-3DSX7DYG.cjs +23 -0
- package/dist/learn-OPOH5L43.js +23 -0
- package/dist/login-GST7MWXJ.cjs +27 -0
- package/dist/login-Q7DZKAX4.js +27 -0
- package/dist/logout-2G7OUK7I.cjs +24 -0
- package/dist/logout-FNBBL2UI.js +24 -0
- package/dist/mcp-AH3MMUBU.js +21 -0
- package/dist/mcp-DW7R63IB.cjs +21 -0
- package/dist/{mcp-install-2FEROZTL.js → mcp-install-222PCKSW.js} +18 -10
- package/dist/{mcp-install-WM6BQRI5.cjs → mcp-install-IA4ZS2SV.cjs} +22 -14
- package/dist/memory-6NX3DAIY.cjs +10 -0
- package/dist/{memory-J73WZH2I.js → memory-VB46T5H3.js} +2 -2
- package/dist/model-64NAELFS.cjs +10 -0
- package/dist/{model-AES267IN.js → model-SJJG64AM.js} +2 -2
- package/dist/new-DU5SOOOY.cjs +12 -0
- package/dist/{new-5CLF3MKH.js → new-ERZ5C6CN.js} +3 -3
- package/dist/onboarding-2U2BV2KE.cjs +36 -0
- package/dist/onboarding-ZQXMPSMJ.js +36 -0
- package/dist/permissions-7ACNFK7A.js +10 -0
- package/dist/permissions-GSNNV7RJ.cjs +10 -0
- package/dist/plan-XEJMOT55.cjs +13 -0
- package/dist/{plan-65HMS5HQ.js → plan-YYUAXPTL.js} +3 -1
- package/dist/pr-review-CW6J7P62.cjs +9 -0
- package/dist/pr-review-YZSBQVT2.js +9 -0
- package/dist/{quit-XDZYRSPU.js → quit-WY6T267G.js} +2 -2
- package/dist/quit-XIRE2KRE.cjs +10 -0
- package/dist/rawMode-6W5AXAKI.cjs +7 -0
- package/dist/rawMode-GFNLXQPU.js +7 -0
- package/dist/{registry-PTHWERKC.js → registry-4DXUDKJN.js} +29 -44
- package/dist/{registry-IVT4G2RT.cjs → registry-UEO3ETZ7.cjs} +65 -80
- package/dist/repeat-P4FAPE3Y.cjs +17 -0
- package/dist/{repeat-EVCWUL6Z.js → repeat-RALE6AUO.js} +7 -3
- package/dist/resume-RQZ3WXBP.cjs +17 -0
- package/dist/resume-XSXZMDMD.js +17 -0
- package/dist/review-QHP2KP4Q.js +9 -0
- package/dist/review-UWHWQHCB.cjs +9 -0
- package/dist/ripgrep-67SCU2BA.cjs +9 -0
- package/dist/ripgrep-VHJQQ55W.js +9 -0
- package/dist/rpc-XH7QLN4H.js +3874 -0
- package/dist/rpc-YF54T7JU.cjs +3874 -0
- package/dist/search-VXXFGZWU.cjs +21 -0
- package/dist/search-YAWGX7P7.js +21 -0
- package/dist/{sessions-6GWEBMKS.js → sessions-NJYHJOEL.js} +2 -2
- package/dist/sessions-OSG3UJEZ.cjs +10 -0
- package/dist/settings-SO2UIGWV.cjs +42 -0
- package/dist/settings-ZXUQH3DO.js +42 -0
- package/dist/setup-KG7EGKF5.js +30 -0
- package/dist/setup-RSOPCQ57.cjs +30 -0
- package/dist/share-WFAGZ5PY.js +17 -0
- package/dist/share-ZU3SGACF.cjs +17 -0
- package/dist/skills-KBVAQAD2.cjs +29 -0
- package/dist/skills-NBTNDVAY.js +29 -0
- package/dist/{skills-ZZCIAS7C.js → skills-OB6RDW7D.js} +10 -7
- package/dist/{skills-PG542VEB.cjs → skills-ZROBG3RZ.cjs} +13 -10
- package/dist/{skills-install-SRC3Z2MS.js → skills-install-BHTIEMKH.js} +21 -70
- package/dist/{skills-install-67DOBPJC.cjs → skills-install-ILX6QVEF.cjs} +34 -83
- package/dist/skills-new-B45VQ2PP.cjs +18 -0
- package/dist/skills-new-YMRP2HNO.js +18 -0
- package/dist/slashCommands-53VYIBJU.js +105 -0
- package/dist/slashCommands-BG2RGGZ6.cjs +105 -0
- package/dist/status-CQ2IUOVK.cjs +24 -0
- package/dist/status-E7IGNVPC.js +24 -0
- package/dist/summarizer-DGPHE5IQ.js +17 -0
- package/dist/summarizer-JNXLUAQG.cjs +17 -0
- package/dist/sync-7C25MOT2.js +22 -0
- package/dist/{sync-VU2NSJ4O.js → sync-OCJN4ZSO.js} +3 -3
- package/dist/sync-XRP46IVG.cjs +40 -0
- package/dist/sync-ZMFVE7T4.cjs +22 -0
- package/dist/{teammate-SXRVXNQV.cjs → teammate-D77B6QRT.cjs} +31 -9
- package/dist/{teammate-SD26GR37.js → teammate-EZCMHOIL.js} +30 -8
- package/dist/templates-ARG2VRWW.cjs +11 -0
- package/dist/templates-UGVZV3KJ.js +11 -0
- package/dist/theme-KKRDE6P7.cjs +22 -0
- package/dist/theme-XF7XIWBQ.js +22 -0
- package/dist/tools-3PPTTKFV.js +9 -0
- package/dist/tools-THIQA7WC.cjs +9 -0
- package/dist/ui/questionModal.cjs +8 -5
- package/dist/ui/questionModal.js +7 -4
- package/dist/{undo-OL2EDBRY.js → undo-GNUTFXCW.js} +2 -2
- package/dist/undo-U4KN7QQM.cjs +10 -0
- package/dist/usage-QSTNSDAO.js +24 -0
- package/dist/usage-YDEMQBNQ.cjs +24 -0
- package/dist/web-3BA2WV37.cjs +37 -0
- package/dist/web-6FYGBX5K.js +37 -0
- package/dist/workspaceSafety-MDJGHK6D.cjs +9 -0
- package/dist/workspaceSafety-XOUMUBVB.js +9 -0
- package/dist/yolo-GF2YD7ZI.js +9 -0
- package/dist/yolo-OGDA7HNC.cjs +9 -0
- package/dist/yoloMode-3DJDA75U.cjs +17 -0
- package/dist/yoloMode-4JOOSU26.js +17 -0
- package/package.json +51 -49
- package/dist/AgentRegistry-HRPN6ZOF.cjs +0 -10
- package/dist/CommunitySkillsCache-KE435RAR.cjs +0 -8
- package/dist/GitHubRegistryFetcher-I45SESIL.cjs +0 -7
- package/dist/LearnAdvisor-FLBA6FDD.js +0 -9
- package/dist/LearnAdvisor-GG3CXQF3.cjs +0 -9
- package/dist/MemoryManager-2LQPIYVE.cjs +0 -8
- package/dist/PermissionManager-X57BXHJ6.cjs +0 -11
- package/dist/ProviderFactory-KPJOGQWF.cjs +0 -9
- package/dist/SessionManager-YBJAZXNO.cjs +0 -10
- package/dist/SkillsRegistry-7O72A6TZ.cjs +0 -9
- package/dist/SubAgent-JT4HZHN7.js +0 -11
- package/dist/SubAgent-VPNYDWAU.cjs +0 -11
- package/dist/SyncApiClient-HQXJL5BT.cjs +0 -11
- package/dist/about-4DB5KTHW.js +0 -12
- package/dist/about-LXAOXZFT.cjs +0 -12
- package/dist/actionExecutor-23JB2WUC.js +0 -19
- package/dist/actionExecutor-X5UEZSKH.cjs +0 -19
- package/dist/add-dir-YC37DMSF.cjs +0 -10
- package/dist/agents-YF3BSUU5.js +0 -12
- package/dist/agents-ZOUHPMYR.cjs +0 -12
- package/dist/agents-new-HSH4GQPG.js +0 -14
- package/dist/agents-new-VYUDOCE7.cjs +0 -14
- package/dist/autoSkill-X5W52WOE.cjs +0 -20
- package/dist/automode-SJGM7VEI.cjs +0 -10
- package/dist/chunk-ALYU6VTM.js +0 -105
- package/dist/chunk-B53A2NM2.js +0 -2030
- package/dist/chunk-BJXSNT46.js +0 -100
- package/dist/chunk-CB4E2T5N.cjs +0 -312
- package/dist/chunk-DNUOXBHL.js +0 -539
- package/dist/chunk-EFX2QSZX.cjs +0 -33
- package/dist/chunk-GCXYXLRA.cjs +0 -111
- package/dist/chunk-H2ZRHQQV.js +0 -33
- package/dist/chunk-HNRPK5MY.cjs +0 -85
- package/dist/chunk-HVKOZ2VP.cjs +0 -115
- package/dist/chunk-JJLYWH5Y.cjs +0 -100
- package/dist/chunk-LWUJFGOZ.js +0 -115
- package/dist/chunk-MERYP6AM.cjs +0 -539
- package/dist/chunk-MZAPWNAC.cjs +0 -207
- package/dist/chunk-NTSDP2WB.js +0 -226
- package/dist/chunk-OUZQXMHL.cjs +0 -226
- package/dist/chunk-PGESAU2W.cjs +0 -2030
- package/dist/chunk-SYVYLZZF.cjs +0 -24
- package/dist/chunk-SZOLA6FR.js +0 -111
- package/dist/chunk-VWDHR4HV.js +0 -168
- package/dist/chunk-Y45G6ZO5.cjs +0 -168
- package/dist/chunk-YRLYSQEQ.cjs +0 -105
- package/dist/chunk-ZYVS43MU.js +0 -312
- package/dist/clear-GK4IEUUS.cjs +0 -12
- package/dist/communityInstaller-XXC7RLE4.cjs +0 -19
- package/dist/completion-HWABSAEL.js +0 -14
- package/dist/completion-IUUVQG4D.cjs +0 -14
- package/dist/config-HF7WOLZF.cjs +0 -18
- package/dist/constants-PEO3P2SJ.cjs +0 -21
- package/dist/export-QJAV2FCZ.js +0 -12
- package/dist/export-XSRFXGWU.cjs +0 -12
- package/dist/feedback-4TCIL3ML.cjs +0 -15
- package/dist/feedback-SJ6VVEY3.js +0 -15
- package/dist/filesystem-W56QZUJF.cjs +0 -10
- package/dist/help-ISBVQL3S.cjs +0 -12
- package/dist/history-XQ4GTSFU.cjs +0 -14
- package/dist/hooks-CJNKJ5PF.js +0 -13
- package/dist/hooks-UTMBTAXT.cjs +0 -13
- package/dist/i18n-N7QQ7A5M.cjs +0 -33
- package/dist/ide-RTA4UJV4.js +0 -12
- package/dist/ide-VWVOLIFF.cjs +0 -12
- package/dist/immediateCommandRouter-BW34JNXL.js +0 -9
- package/dist/immediateCommandRouter-SHOVNB5X.cjs +0 -9
- package/dist/import-ZLJVONXH.cjs +0 -10
- package/dist/init-TBKAB4LZ.cjs +0 -10
- package/dist/language-MDSHEXHB.cjs +0 -18
- package/dist/language-PXTQSHIG.js +0 -18
- package/dist/learn-623TW5EK.cjs +0 -20
- package/dist/learn-BCPV7GM2.js +0 -20
- package/dist/localProjectPermissions-BHQXEWZJ.cjs +0 -18
- package/dist/localProjectPermissions-GMOUYQM6.js +0 -18
- package/dist/login-QMVEETWJ.js +0 -20
- package/dist/login-QYMXAL3K.cjs +0 -20
- package/dist/logout-2CMTDAOJ.js +0 -18
- package/dist/logout-ZOHVZAUK.cjs +0 -18
- package/dist/mcp-IUVKK65S.js +0 -18
- package/dist/mcp-TXC7PYG3.cjs +0 -18
- package/dist/memory-WRIHDEPK.cjs +0 -10
- package/dist/model-RLP75SF5.cjs +0 -10
- package/dist/new-HLSFL6A4.cjs +0 -12
- package/dist/permissions-GP6FTGZ2.js +0 -13
- package/dist/permissions-O6EKKPOG.cjs +0 -13
- package/dist/plan-MCAXDIM2.cjs +0 -11
- package/dist/quit-TQX6GXA5.cjs +0 -10
- package/dist/repeat-BSPS5TWD.cjs +0 -13
- package/dist/resume-2GOPDLL4.cjs +0 -13
- package/dist/resume-37IUVDA6.js +0 -13
- package/dist/search-7KUSHIBL.cjs +0 -17
- package/dist/search-OJGDRIMA.js +0 -17
- package/dist/sessions-CYYCHSQG.cjs +0 -10
- package/dist/settings-2D7CAO66.cjs +0 -30
- package/dist/settings-BXR6SBJP.js +0 -30
- package/dist/share-BXQY5IQU.js +0 -14
- package/dist/share-OSFXZBGS.cjs +0 -14
- package/dist/skills-FL6O6AOM.cjs +0 -26
- package/dist/skills-PNKQZRNK.js +0 -26
- package/dist/skills-new-XFMEHHIF.cjs +0 -15
- package/dist/skills-new-ZNZPHUKS.js +0 -15
- package/dist/slashCommands-LLCNPK3X.js +0 -76
- package/dist/slashCommands-RXZZS6RE.cjs +0 -76
- package/dist/status-BCECUJXT.cjs +0 -11
- package/dist/status-EFO7MQU3.js +0 -11
- package/dist/sync-IJYJ6KKM.js +0 -18
- package/dist/sync-LFT6SBPF.cjs +0 -18
- package/dist/sync-U7SDPBNZ.cjs +0 -40
- package/dist/theme-AWBHSG7J.cjs +0 -18
- package/dist/theme-TQLBPJ2E.js +0 -18
- package/dist/undo-IBBGP7A2.cjs +0 -10
|
@@ -0,0 +1,3874 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FileActionManager
|
|
3
|
+
} from "./chunk-ZQAT5VT5.js";
|
|
4
|
+
import {
|
|
5
|
+
AutohandAgent
|
|
6
|
+
} from "./chunk-CCIDL4SA.js";
|
|
7
|
+
import "./chunk-XAV24VYN.js";
|
|
8
|
+
import {
|
|
9
|
+
normalizePermissionPromptResponse
|
|
10
|
+
} from "./chunk-ZPLCAXJW.js";
|
|
11
|
+
import "./chunk-7IRQ7JEH.js";
|
|
12
|
+
import "./chunk-U2QUMKCB.js";
|
|
13
|
+
import {
|
|
14
|
+
McpClientManager
|
|
15
|
+
} from "./chunk-GNBBIAMD.js";
|
|
16
|
+
import "./chunk-ZNGRLCFQ.js";
|
|
17
|
+
import "./chunk-SNDDZG5H.js";
|
|
18
|
+
import "./chunk-ES2HJQ4N.js";
|
|
19
|
+
import "./chunk-6R25D2H5.js";
|
|
20
|
+
import "./chunk-26G7YGOW.js";
|
|
21
|
+
import "./chunk-KWXGDSYT.js";
|
|
22
|
+
import "./chunk-S5QKRA2V.js";
|
|
23
|
+
import "./chunk-PGFLPURU.js";
|
|
24
|
+
import "./chunk-QEGOB6QV.js";
|
|
25
|
+
import "./chunk-M5DK524Z.js";
|
|
26
|
+
import "./chunk-JMN3GZU6.js";
|
|
27
|
+
import "./chunk-7PJKTSRN.js";
|
|
28
|
+
import "./chunk-5JTTM5SC.js";
|
|
29
|
+
import "./chunk-2H5O745H.js";
|
|
30
|
+
import "./chunk-BP37FVBM.js";
|
|
31
|
+
import "./chunk-FFHSCM5M.js";
|
|
32
|
+
import "./chunk-3ZOOH44N.js";
|
|
33
|
+
import "./chunk-WPE2XHVX.js";
|
|
34
|
+
import "./chunk-2IW5YFJ4.js";
|
|
35
|
+
import "./chunk-HBXAA3XB.js";
|
|
36
|
+
import "./chunk-3OEDGIFW.js";
|
|
37
|
+
import "./chunk-WNUVPKBW.js";
|
|
38
|
+
import "./chunk-RAKO7UN7.js";
|
|
39
|
+
import "./chunk-CECH6QQP.js";
|
|
40
|
+
import "./chunk-FBQJZKFX.js";
|
|
41
|
+
import "./chunk-NB6M6ESM.js";
|
|
42
|
+
import "./chunk-Q3BS6FPM.js";
|
|
43
|
+
import "./chunk-4XVLNOFA.js";
|
|
44
|
+
import "./chunk-DNSD7DVJ.js";
|
|
45
|
+
import "./chunk-SPQ7QIQ6.js";
|
|
46
|
+
import "./chunk-QBYGMMDD.js";
|
|
47
|
+
import "./chunk-O5GI6SR3.js";
|
|
48
|
+
import "./chunk-C5QIQQ37.js";
|
|
49
|
+
import "./chunk-44ZWOBTI.js";
|
|
50
|
+
import "./chunk-4E7SHPNQ.js";
|
|
51
|
+
import "./chunk-QHPFA6OE.js";
|
|
52
|
+
import "./chunk-H426KOGY.js";
|
|
53
|
+
import "./chunk-WNJXIACY.js";
|
|
54
|
+
import "./chunk-XZVDYC5U.js";
|
|
55
|
+
import "./chunk-DGBPWODD.js";
|
|
56
|
+
import {
|
|
57
|
+
ConversationManager
|
|
58
|
+
} from "./chunk-HQUSEWT4.js";
|
|
59
|
+
import "./chunk-TR6NECEZ.js";
|
|
60
|
+
import "./chunk-24QIWILL.js";
|
|
61
|
+
import "./chunk-2NUX2RAI.js";
|
|
62
|
+
import "./chunk-OIGYWOL6.js";
|
|
63
|
+
import "./chunk-SDLY4X3G.js";
|
|
64
|
+
import "./chunk-HXHE2KAO.js";
|
|
65
|
+
import "./chunk-65LRPW5W.js";
|
|
66
|
+
import "./chunk-YXM6SA7P.js";
|
|
67
|
+
import "./chunk-RS2E32YB.js";
|
|
68
|
+
import "./chunk-SRMGWMQO.js";
|
|
69
|
+
import "./chunk-SVLBJMYO.js";
|
|
70
|
+
import "./chunk-PZZMIYII.js";
|
|
71
|
+
import "./chunk-6HF6XSCC.js";
|
|
72
|
+
import "./chunk-EYHKL4QC.js";
|
|
73
|
+
import "./chunk-ZK6HOR62.js";
|
|
74
|
+
import "./chunk-P4FUTSVK.js";
|
|
75
|
+
import "./chunk-YC5OBZQU.js";
|
|
76
|
+
import "./chunk-H4D2Q2AL.js";
|
|
77
|
+
import {
|
|
78
|
+
GoalManager
|
|
79
|
+
} from "./chunk-SZD45IDG.js";
|
|
80
|
+
import "./chunk-W3X6PAC7.js";
|
|
81
|
+
import "./chunk-JMJRFSNJ.js";
|
|
82
|
+
import "./chunk-TSV4LVHK.js";
|
|
83
|
+
import "./chunk-SFFEKZGC.js";
|
|
84
|
+
import "./chunk-TYBPTKFT.js";
|
|
85
|
+
import "./chunk-UR27UDTB.js";
|
|
86
|
+
import "./chunk-CFAWTLSC.js";
|
|
87
|
+
import "./chunk-I2ZK3AOD.js";
|
|
88
|
+
import {
|
|
89
|
+
buildPermissionSettingsFromYolo,
|
|
90
|
+
normalizeYoloInput,
|
|
91
|
+
parseYoloPattern
|
|
92
|
+
} from "./chunk-4LMUDS2K.js";
|
|
93
|
+
import "./chunk-HTU4W3GB.js";
|
|
94
|
+
import "./chunk-KMP6Y3LJ.js";
|
|
95
|
+
import "./chunk-YVQI26H4.js";
|
|
96
|
+
import "./chunk-HSWWM6AM.js";
|
|
97
|
+
import "./chunk-TH26BQJG.js";
|
|
98
|
+
import {
|
|
99
|
+
ProviderFactory,
|
|
100
|
+
modelSupportsImages
|
|
101
|
+
} from "./chunk-JPFRI4L4.js";
|
|
102
|
+
import {
|
|
103
|
+
ImageManager
|
|
104
|
+
} from "./chunk-MANJ67D3.js";
|
|
105
|
+
import "./chunk-VUGOOGHB.js";
|
|
106
|
+
import {
|
|
107
|
+
getPlanModeManager
|
|
108
|
+
} from "./chunk-LUMV3DB2.js";
|
|
109
|
+
import "./chunk-BQU3HAE7.js";
|
|
110
|
+
import "./chunk-575PXZX7.js";
|
|
111
|
+
import {
|
|
112
|
+
GOAL_FEATURE_DISABLED_MESSAGE,
|
|
113
|
+
isGoalFeatureEnabled
|
|
114
|
+
} from "./chunk-7MY4JHER.js";
|
|
115
|
+
import "./chunk-FP46B4X3.js";
|
|
116
|
+
import "./chunk-QRQF3556.js";
|
|
117
|
+
import "./chunk-V5ELP2XE.js";
|
|
118
|
+
import "./chunk-EEHWALXA.js";
|
|
119
|
+
import "./chunk-PTTZI4QZ.js";
|
|
120
|
+
import "./chunk-UWZ4G3SQ.js";
|
|
121
|
+
import "./chunk-ZUYYHKQA.js";
|
|
122
|
+
import "./chunk-46MTALKD.js";
|
|
123
|
+
import "./chunk-YQDI753V.js";
|
|
124
|
+
import "./chunk-MMKZSJUN.js";
|
|
125
|
+
import "./chunk-4567QNRB.js";
|
|
126
|
+
import {
|
|
127
|
+
validateWorkspacePath
|
|
128
|
+
} from "./chunk-KA2U6MY2.js";
|
|
129
|
+
import {
|
|
130
|
+
isSessionWorktreeEnabled,
|
|
131
|
+
prepareSessionWorktree
|
|
132
|
+
} from "./chunk-C46B72VK.js";
|
|
133
|
+
import "./chunk-WQ3VJXZB.js";
|
|
134
|
+
import {
|
|
135
|
+
attachBrowserHandoff,
|
|
136
|
+
attachLatestBrowserHandoff,
|
|
137
|
+
createBrowserHandoff
|
|
138
|
+
} from "./chunk-GSDV75A5.js";
|
|
139
|
+
import {
|
|
140
|
+
checkAuthenticated
|
|
141
|
+
} from "./chunk-6AYJCDTA.js";
|
|
142
|
+
import "./chunk-GLBAF54O.js";
|
|
143
|
+
import "./chunk-7DJJGKM6.js";
|
|
144
|
+
import "./chunk-JB3JCYBJ.js";
|
|
145
|
+
import {
|
|
146
|
+
classifyApiError
|
|
147
|
+
} from "./chunk-FQVG6ZHF.js";
|
|
148
|
+
import "./chunk-X3TI5TJJ.js";
|
|
149
|
+
import "./chunk-NZ3ZWLUW.js";
|
|
150
|
+
import "./chunk-HZWU6IO3.js";
|
|
151
|
+
import "./chunk-CSTUTDTH.js";
|
|
152
|
+
import {
|
|
153
|
+
loadConfig
|
|
154
|
+
} from "./chunk-IEPLQ47J.js";
|
|
155
|
+
import "./chunk-5A7ZL64N.js";
|
|
156
|
+
import "./chunk-YZWE7XSM.js";
|
|
157
|
+
import "./chunk-LANGD5CO.js";
|
|
158
|
+
import "./chunk-NBGOIFKP.js";
|
|
159
|
+
import "./chunk-JAQO6XDB.js";
|
|
160
|
+
import "./chunk-SHRLFX6F.js";
|
|
161
|
+
import "./chunk-UOQECODR.js";
|
|
162
|
+
import {
|
|
163
|
+
checkWorkspaceSafety
|
|
164
|
+
} from "./chunk-PB7W7R72.js";
|
|
165
|
+
import "./chunk-LEZEWKPA.js";
|
|
166
|
+
import "./chunk-L6OH44HL.js";
|
|
167
|
+
import "./chunk-QGM4M3NI.js";
|
|
168
|
+
|
|
169
|
+
// src/modes/rpc/index.ts
|
|
170
|
+
import fs from "fs-extra";
|
|
171
|
+
import path from "path";
|
|
172
|
+
|
|
173
|
+
// src/modes/rpc/types.ts
|
|
174
|
+
var JSON_RPC_ERROR_CODES = {
|
|
175
|
+
// Standard JSON-RPC 2.0 errors
|
|
176
|
+
PARSE_ERROR: -32700,
|
|
177
|
+
INVALID_REQUEST: -32600,
|
|
178
|
+
METHOD_NOT_FOUND: -32601,
|
|
179
|
+
INVALID_PARAMS: -32602,
|
|
180
|
+
INTERNAL_ERROR: -32603,
|
|
181
|
+
// Server errors (reserved for implementation-defined errors: -32000 to -32099)
|
|
182
|
+
EXECUTION_ERROR: -32e3,
|
|
183
|
+
PERMISSION_DENIED: -32001,
|
|
184
|
+
TIMEOUT: -32002,
|
|
185
|
+
AGENT_BUSY: -32003,
|
|
186
|
+
ABORTED: -32004
|
|
187
|
+
};
|
|
188
|
+
var RPC_METHODS = {
|
|
189
|
+
// Client -> Server requests
|
|
190
|
+
PROMPT: "autohand.prompt",
|
|
191
|
+
ABORT: "autohand.abort",
|
|
192
|
+
RESET: "autohand.reset",
|
|
193
|
+
GET_STATE: "autohand.getState",
|
|
194
|
+
GET_MESSAGES: "autohand.getMessages",
|
|
195
|
+
BROWSER_HANDOFF_CREATE: "autohand.browserHandoff.create",
|
|
196
|
+
BROWSER_HANDOFF_ATTACH: "autohand.browserHandoff.attach",
|
|
197
|
+
BROWSER_HANDOFF_ATTACH_LATEST: "autohand.browserHandoff.attachLatest",
|
|
198
|
+
PERMISSION_RESPONSE: "autohand.permissionResponse",
|
|
199
|
+
PERMISSION_ACKNOWLEDGED: "autohand.permissionAcknowledged",
|
|
200
|
+
DIRECTORY_ACCESS_RESPONSE: "autohand.directoryAccessResponse",
|
|
201
|
+
DIRECTORY_ACCESS_ACKNOWLEDGED: "autohand.directoryAccessAcknowledged",
|
|
202
|
+
// Multi-file change preview
|
|
203
|
+
CHANGES_DECISION: "autohand.changesDecision",
|
|
204
|
+
// Skills management (non-interactive for RPC mode)
|
|
205
|
+
GET_SKILLS_REGISTRY: "autohand.getSkillsRegistry",
|
|
206
|
+
INSTALL_SKILL: "autohand.installSkill",
|
|
207
|
+
// Auto-mode control
|
|
208
|
+
AUTOMODE_START: "autohand.automode.start",
|
|
209
|
+
AUTOMODE_STATUS: "autohand.automode.status",
|
|
210
|
+
AUTOMODE_PAUSE: "autohand.automode.pause",
|
|
211
|
+
AUTOMODE_RESUME: "autohand.automode.resume",
|
|
212
|
+
AUTOMODE_CANCEL: "autohand.automode.cancel",
|
|
213
|
+
AUTOMODE_GET_LOG: "autohand.automode.getLog",
|
|
214
|
+
// Plan mode control
|
|
215
|
+
PLAN_MODE_SET: "autohand.planModeSet",
|
|
216
|
+
// Session history
|
|
217
|
+
GET_HISTORY: "autohand.getHistory",
|
|
218
|
+
GET_SESSION: "autohand.getSession",
|
|
219
|
+
// YOLO mode control
|
|
220
|
+
YOLO_SET: "autohand.yoloSet",
|
|
221
|
+
// MCP (Model Context Protocol) management
|
|
222
|
+
MCP_LIST_SERVERS: "autohand.mcp.listServers",
|
|
223
|
+
MCP_LIST_TOOLS: "autohand.mcp.listTools",
|
|
224
|
+
MCP_SET_VSCODE_TOOLS: "autohand.mcp.setVscodeTools",
|
|
225
|
+
MCP_INVOKE_RESPONSE: "autohand.mcp.invokeResponse",
|
|
226
|
+
MCP_GET_SERVER_CONFIGS: "autohand.mcp.getServerConfigs",
|
|
227
|
+
LEARN_RECOMMEND: "autohand.learn.recommend",
|
|
228
|
+
LEARN_UPDATE: "autohand.learn.update",
|
|
229
|
+
LEARN_GENERATE: "autohand.learn.generate",
|
|
230
|
+
SKILLS_SEARCH: "autohand.skills.search",
|
|
231
|
+
SKILLS_TRENDING: "autohand.skills.trending",
|
|
232
|
+
SKILLS_REMOVE: "autohand.skills.remove",
|
|
233
|
+
SKILLS_INSTALL: "autohand.skills.install",
|
|
234
|
+
// SDK control methods
|
|
235
|
+
SET_PERMISSION_MODE: "autohand.permissionModeSet",
|
|
236
|
+
SET_MODEL: "autohand.modelSet",
|
|
237
|
+
SET_MAX_THINKING_TOKENS: "autohand.maxThinkingTokensSet",
|
|
238
|
+
APPLY_FLAG_SETTINGS: "autohand.applyFlagSettings",
|
|
239
|
+
GET_SUPPORTED_MODELS: "autohand.getSupportedModels",
|
|
240
|
+
GET_SUPPORTED_COMMANDS: "autohand.getSupportedCommands",
|
|
241
|
+
GET_TOOLS_REGISTRY: "autohand.getToolsRegistry",
|
|
242
|
+
GET_CONTEXT_USAGE: "autohand.getContextUsage",
|
|
243
|
+
RELOAD_PLUGINS: "autohand.reloadPlugins",
|
|
244
|
+
GET_ACCOUNT_INFO: "autohand.getAccountInfo",
|
|
245
|
+
MCP_TOGGLE_SERVER: "autohand.mcp.toggleServer",
|
|
246
|
+
MCP_RECONNECT_SERVER: "autohand.mcp.reconnectServer",
|
|
247
|
+
MCP_SET_SERVERS: "autohand.mcp.setServers",
|
|
248
|
+
// Context compaction control
|
|
249
|
+
SET_CONTEXT_COMPACT: "autohand.setContextCompact",
|
|
250
|
+
// Setup wizard
|
|
251
|
+
SETUP: "autohand.setup",
|
|
252
|
+
GOAL_GET: "autohand.goal.get",
|
|
253
|
+
GOAL_CREATE: "autohand.goal.create",
|
|
254
|
+
GOAL_UPDATE: "autohand.goal.update",
|
|
255
|
+
GOAL_CLEAR: "autohand.goal.clear",
|
|
256
|
+
GOAL_QUEUE: "autohand.goal.queue",
|
|
257
|
+
GOAL_START_QUEUED: "autohand.goal.startQueued",
|
|
258
|
+
GOAL_LIST_TEMPLATES: "autohand.goal.listTemplates"
|
|
259
|
+
};
|
|
260
|
+
var RPC_NOTIFICATIONS = {
|
|
261
|
+
AGENT_START: "autohand.agentStart",
|
|
262
|
+
AGENT_END: "autohand.agentEnd",
|
|
263
|
+
PING: "autohand.ping",
|
|
264
|
+
TURN_START: "autohand.turnStart",
|
|
265
|
+
TURN_END: "autohand.turnEnd",
|
|
266
|
+
MESSAGE_START: "autohand.messageStart",
|
|
267
|
+
MESSAGE_UPDATE: "autohand.messageUpdate",
|
|
268
|
+
MESSAGE_END: "autohand.messageEnd",
|
|
269
|
+
TOOL_START: "autohand.toolStart",
|
|
270
|
+
TOOL_UPDATE: "autohand.toolUpdate",
|
|
271
|
+
TOOL_END: "autohand.toolEnd",
|
|
272
|
+
PERMISSION_REQUEST: "autohand.permissionRequest",
|
|
273
|
+
DIRECTORY_ACCESS_REQUEST: "autohand.directoryAccessRequest",
|
|
274
|
+
ERROR: "autohand.error",
|
|
275
|
+
// Multi-file change preview notifications
|
|
276
|
+
CHANGES_BATCH_START: "autohand.changesBatchStart",
|
|
277
|
+
CHANGES_BATCH_UPDATE: "autohand.changesBatchUpdate",
|
|
278
|
+
CHANGES_BATCH_END: "autohand.changesBatchEnd",
|
|
279
|
+
// Hook lifecycle notifications
|
|
280
|
+
HOOK_PRE_TOOL: "autohand.hook.preTool",
|
|
281
|
+
HOOK_POST_TOOL: "autohand.hook.postTool",
|
|
282
|
+
HOOK_FILE_MODIFIED: "autohand.hook.fileModified",
|
|
283
|
+
HOOK_PRE_PROMPT: "autohand.hook.prePrompt",
|
|
284
|
+
HOOK_POST_RESPONSE: "autohand.hook.postResponse",
|
|
285
|
+
HOOK_SESSION_ERROR: "autohand.hook.sessionError",
|
|
286
|
+
HOOK_STOP: "autohand.hook.stop",
|
|
287
|
+
HOOK_SESSION_START: "autohand.hook.sessionStart",
|
|
288
|
+
HOOK_SESSION_END: "autohand.hook.sessionEnd",
|
|
289
|
+
HOOK_SUBAGENT_STOP: "autohand.hook.subagentStop",
|
|
290
|
+
HOOK_PERMISSION_REQUEST: "autohand.hook.permissionRequest",
|
|
291
|
+
HOOK_NOTIFICATION: "autohand.hook.notification",
|
|
292
|
+
// Auto-mode lifecycle notifications
|
|
293
|
+
AUTOMODE_START: "autohand.automode.start",
|
|
294
|
+
AUTOMODE_ITERATION: "autohand.automode.iteration",
|
|
295
|
+
AUTOMODE_CHECKPOINT: "autohand.automode.checkpoint",
|
|
296
|
+
AUTOMODE_PAUSE: "autohand.automode.pause",
|
|
297
|
+
AUTOMODE_RESUME: "autohand.automode.resume",
|
|
298
|
+
AUTOMODE_CANCEL: "autohand.automode.cancel",
|
|
299
|
+
AUTOMODE_COMPLETE: "autohand.automode.complete",
|
|
300
|
+
AUTOMODE_ERROR: "autohand.automode.error",
|
|
301
|
+
// Mode change notifications
|
|
302
|
+
MODE_CHANGE: "autohand.modeChange",
|
|
303
|
+
// Pipe mode notifications
|
|
304
|
+
PIPE_OUTPUT: "autohand.pipe.output",
|
|
305
|
+
PIPE_COMPLETE: "autohand.pipe.complete",
|
|
306
|
+
PIPE_ERROR: "autohand.pipe.error",
|
|
307
|
+
// MCP bridge notifications (Server -> Client)
|
|
308
|
+
MCP_INVOKE_REQUEST: "autohand.mcp.invokeRequest",
|
|
309
|
+
MCP_TOOLS_CHANGED: "autohand.mcp.toolsChanged",
|
|
310
|
+
LEARN_INSTALL_COMPLETE: "autohand.learn.installComplete",
|
|
311
|
+
LEARN_SECURITY_WARNING: "autohand.learn.securityWarning",
|
|
312
|
+
LEARN_PROGRESS: "autohand.learn.progress",
|
|
313
|
+
SCHEDULE_TRIGGERED: "autohand.schedule.triggered",
|
|
314
|
+
// Setup wizard notifications
|
|
315
|
+
SETUP_STARTED: "autohand.setup.started",
|
|
316
|
+
SETUP_STEP_START: "autohand.setup.stepStart",
|
|
317
|
+
SETUP_STEP_COMPLETE: "autohand.setup.stepComplete",
|
|
318
|
+
SETUP_CANCELLED: "autohand.setup.cancelled",
|
|
319
|
+
SETUP_ERROR: "autohand.setup.error",
|
|
320
|
+
SETUP_COMPLETE: "autohand.setup.complete",
|
|
321
|
+
// Context lifecycle notifications
|
|
322
|
+
HOOK_CONTEXT_COMPACTED: "autohand.hook.contextCompacted",
|
|
323
|
+
HOOK_CONTEXT_OVERFLOW: "autohand.hook.contextOverflow",
|
|
324
|
+
HOOK_CONTEXT_WARNING: "autohand.hook.contextWarning",
|
|
325
|
+
HOOK_CONTEXT_CRITICAL: "autohand.hook.contextCritical"
|
|
326
|
+
};
|
|
327
|
+
var MAX_IMAGE_SIZE = 10 * 1024 * 1024;
|
|
328
|
+
var VALID_IMAGE_MIME_TYPES = [
|
|
329
|
+
"image/png",
|
|
330
|
+
"image/jpeg",
|
|
331
|
+
"image/gif",
|
|
332
|
+
"image/webp"
|
|
333
|
+
];
|
|
334
|
+
function isValidImageMimeType(mimeType) {
|
|
335
|
+
return VALID_IMAGE_MIME_TYPES.includes(mimeType);
|
|
336
|
+
}
|
|
337
|
+
function isJsonRpcRequest(obj) {
|
|
338
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
339
|
+
const req = obj;
|
|
340
|
+
return req.jsonrpc === "2.0" && typeof req.method === "string";
|
|
341
|
+
}
|
|
342
|
+
function isJsonRpcResponse(obj) {
|
|
343
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
344
|
+
const res = obj;
|
|
345
|
+
return res.jsonrpc === "2.0" && ("result" in res || "error" in res);
|
|
346
|
+
}
|
|
347
|
+
function isJsonRpcBatch(obj) {
|
|
348
|
+
return Array.isArray(obj) && obj.length > 0;
|
|
349
|
+
}
|
|
350
|
+
function isNotification(request) {
|
|
351
|
+
return request.id === void 0;
|
|
352
|
+
}
|
|
353
|
+
function createRequest(method, params, id) {
|
|
354
|
+
const request = {
|
|
355
|
+
jsonrpc: "2.0",
|
|
356
|
+
method
|
|
357
|
+
};
|
|
358
|
+
if (params !== void 0) {
|
|
359
|
+
request.params = params;
|
|
360
|
+
}
|
|
361
|
+
if (id !== void 0) {
|
|
362
|
+
request.id = id;
|
|
363
|
+
}
|
|
364
|
+
return request;
|
|
365
|
+
}
|
|
366
|
+
function createResponse(id, result) {
|
|
367
|
+
return {
|
|
368
|
+
jsonrpc: "2.0",
|
|
369
|
+
result,
|
|
370
|
+
id
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
function createErrorResponse(id, code, message, data) {
|
|
374
|
+
const response = {
|
|
375
|
+
jsonrpc: "2.0",
|
|
376
|
+
error: { code, message },
|
|
377
|
+
id
|
|
378
|
+
};
|
|
379
|
+
if (data !== void 0) {
|
|
380
|
+
response.error.data = data;
|
|
381
|
+
}
|
|
382
|
+
return response;
|
|
383
|
+
}
|
|
384
|
+
function createNotification(method, params) {
|
|
385
|
+
const notification = {
|
|
386
|
+
jsonrpc: "2.0",
|
|
387
|
+
method
|
|
388
|
+
};
|
|
389
|
+
if (params !== void 0) {
|
|
390
|
+
notification.params = params;
|
|
391
|
+
}
|
|
392
|
+
return notification;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/modes/rpc/adapter.ts
|
|
396
|
+
import crypto from "crypto";
|
|
397
|
+
|
|
398
|
+
// src/modes/rpc/protocol.ts
|
|
399
|
+
function parseRequest(line) {
|
|
400
|
+
const trimmed = line.trim();
|
|
401
|
+
if (!trimmed) {
|
|
402
|
+
return {
|
|
403
|
+
type: "error",
|
|
404
|
+
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
405
|
+
message: "Empty request"
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
let parsed;
|
|
409
|
+
try {
|
|
410
|
+
parsed = JSON.parse(trimmed);
|
|
411
|
+
} catch {
|
|
412
|
+
return {
|
|
413
|
+
type: "error",
|
|
414
|
+
code: JSON_RPC_ERROR_CODES.PARSE_ERROR,
|
|
415
|
+
message: "Parse error: Invalid JSON"
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
if (isJsonRpcBatch(parsed)) {
|
|
419
|
+
const validRequests = [];
|
|
420
|
+
for (const item of parsed) {
|
|
421
|
+
if (isJsonRpcRequest(item)) {
|
|
422
|
+
validRequests.push(item);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (validRequests.length === 0) {
|
|
426
|
+
return {
|
|
427
|
+
type: "error",
|
|
428
|
+
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
429
|
+
message: "Invalid batch: No valid requests"
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
return { type: "batch", requests: validRequests };
|
|
433
|
+
}
|
|
434
|
+
if (isJsonRpcRequest(parsed)) {
|
|
435
|
+
return { type: "single", request: parsed };
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
type: "error",
|
|
439
|
+
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
440
|
+
message: "Invalid request: Missing jsonrpc version or method"
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function serialize(obj) {
|
|
444
|
+
try {
|
|
445
|
+
return JSON.stringify(obj);
|
|
446
|
+
} catch (error) {
|
|
447
|
+
const message = error instanceof Error ? error.message : "Unknown serialization error";
|
|
448
|
+
process.stderr.write(`[RPC] Serialization error: ${message}
|
|
449
|
+
`);
|
|
450
|
+
return JSON.stringify({
|
|
451
|
+
jsonrpc: "2.0",
|
|
452
|
+
error: {
|
|
453
|
+
code: JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
454
|
+
message: `Serialization failed: ${message}`
|
|
455
|
+
},
|
|
456
|
+
id: null
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function serializeBatch(responses) {
|
|
461
|
+
try {
|
|
462
|
+
return JSON.stringify(responses);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
const message = error instanceof Error ? error.message : "Unknown serialization error";
|
|
465
|
+
process.stderr.write(`[RPC] Batch serialization error: ${message}
|
|
466
|
+
`);
|
|
467
|
+
return JSON.stringify([{
|
|
468
|
+
jsonrpc: "2.0",
|
|
469
|
+
error: {
|
|
470
|
+
code: JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
471
|
+
message: `Batch serialization failed: ${message}`
|
|
472
|
+
},
|
|
473
|
+
id: null
|
|
474
|
+
}]);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function createTimestamp() {
|
|
478
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
479
|
+
}
|
|
480
|
+
var idCounter = 0;
|
|
481
|
+
function generateId(prefix = "id") {
|
|
482
|
+
return `${prefix}_${++idCounter}_${Date.now()}`;
|
|
483
|
+
}
|
|
484
|
+
var LineReader = class {
|
|
485
|
+
constructor(stream) {
|
|
486
|
+
this.stream = stream;
|
|
487
|
+
this.stream.setEncoding("utf8");
|
|
488
|
+
this.stream.on("data", (chunk) => this.handleData(chunk));
|
|
489
|
+
this.stream.on("end", () => this.handleEnd());
|
|
490
|
+
this.stream.on("close", () => this.handleClose());
|
|
491
|
+
}
|
|
492
|
+
stream;
|
|
493
|
+
buffer = "";
|
|
494
|
+
lineQueue = [];
|
|
495
|
+
resolvers = [];
|
|
496
|
+
closed = false;
|
|
497
|
+
handleData(chunk) {
|
|
498
|
+
this.buffer += chunk;
|
|
499
|
+
let newlineIndex;
|
|
500
|
+
while ((newlineIndex = this.buffer.indexOf("\n")) !== -1) {
|
|
501
|
+
const line = this.buffer.slice(0, newlineIndex);
|
|
502
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
503
|
+
if (line.trim()) {
|
|
504
|
+
this.deliverLine(line);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
handleEnd() {
|
|
509
|
+
if (this.buffer.trim()) {
|
|
510
|
+
this.deliverLine(this.buffer);
|
|
511
|
+
}
|
|
512
|
+
this.buffer = "";
|
|
513
|
+
this.closed = true;
|
|
514
|
+
}
|
|
515
|
+
handleClose() {
|
|
516
|
+
this.closed = true;
|
|
517
|
+
}
|
|
518
|
+
deliverLine(line) {
|
|
519
|
+
if (this.resolvers.length > 0) {
|
|
520
|
+
const resolver = this.resolvers.shift();
|
|
521
|
+
resolver(line);
|
|
522
|
+
} else {
|
|
523
|
+
this.lineQueue.push(line);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Read the next line (async)
|
|
528
|
+
*/
|
|
529
|
+
async readLine() {
|
|
530
|
+
if (this.lineQueue.length > 0) {
|
|
531
|
+
return this.lineQueue.shift();
|
|
532
|
+
}
|
|
533
|
+
if (this.closed) {
|
|
534
|
+
throw new Error("Stream closed");
|
|
535
|
+
}
|
|
536
|
+
return new Promise((resolve) => {
|
|
537
|
+
this.resolvers.push(resolve);
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Check if there are pending lines
|
|
542
|
+
*/
|
|
543
|
+
hasPendingLines() {
|
|
544
|
+
return this.lineQueue.length > 0;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Check if the stream is closed
|
|
548
|
+
*/
|
|
549
|
+
isClosed() {
|
|
550
|
+
return this.closed;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
function writeResponse(id, result) {
|
|
554
|
+
try {
|
|
555
|
+
const response = createResponse(id, result);
|
|
556
|
+
const serialized = serialize(response) + "\n";
|
|
557
|
+
process.stderr.write(`[RPC DEBUG] writeResponse id=${id} size=${serialized.length}b
|
|
558
|
+
`);
|
|
559
|
+
process.stdout.write(serialized);
|
|
560
|
+
} catch (error) {
|
|
561
|
+
const message = error instanceof Error ? error.message : "Unknown write error";
|
|
562
|
+
process.stderr.write(`[RPC] Failed to write response for id '${id}': ${message}
|
|
563
|
+
`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function writeErrorResponse(id, code, message, data) {
|
|
567
|
+
try {
|
|
568
|
+
const response = createErrorResponse(id, code, message, data);
|
|
569
|
+
const serialized = serialize(response) + "\n";
|
|
570
|
+
process.stderr.write(`[RPC DEBUG] writeErrorResponse id=${id} size=${serialized.length}b
|
|
571
|
+
`);
|
|
572
|
+
process.stdout.write(serialized);
|
|
573
|
+
} catch (error) {
|
|
574
|
+
const errMsg = error instanceof Error ? error.message : "Unknown write error";
|
|
575
|
+
process.stderr.write(`[RPC] Failed to write error response: ${errMsg}
|
|
576
|
+
`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function writeBatchResponse(responses) {
|
|
580
|
+
if (responses.length > 0) {
|
|
581
|
+
try {
|
|
582
|
+
const serialized = serializeBatch(responses) + "\n";
|
|
583
|
+
process.stderr.write(`[RPC DEBUG] writeBatchResponse count=${responses.length} size=${serialized.length}b
|
|
584
|
+
`);
|
|
585
|
+
process.stdout.write(serialized);
|
|
586
|
+
} catch (error) {
|
|
587
|
+
const message = error instanceof Error ? error.message : "Unknown write error";
|
|
588
|
+
process.stderr.write(`[RPC] Failed to write batch response: ${message}
|
|
589
|
+
`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function writeNotification(method, params) {
|
|
594
|
+
try {
|
|
595
|
+
const notification = createNotification(method, params);
|
|
596
|
+
const serialized = serialize(notification) + "\n";
|
|
597
|
+
if (method !== "autohand.ping") {
|
|
598
|
+
process.stderr.write(`[RPC DEBUG] writeNotification method=${method} size=${serialized.length}b
|
|
599
|
+
`);
|
|
600
|
+
}
|
|
601
|
+
process.stdout.write(serialized);
|
|
602
|
+
} catch (error) {
|
|
603
|
+
const message = error instanceof Error ? error.message : "Unknown write error";
|
|
604
|
+
process.stderr.write(`[RPC] Failed to write notification '${method}': ${message}
|
|
605
|
+
`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function writeParseError(message = "Parse error") {
|
|
609
|
+
writeErrorResponse(null, JSON_RPC_ERROR_CODES.PARSE_ERROR, message);
|
|
610
|
+
}
|
|
611
|
+
function writeInvalidRequestError(id, message = "Invalid request") {
|
|
612
|
+
writeErrorResponse(id, JSON_RPC_ERROR_CODES.INVALID_REQUEST, message);
|
|
613
|
+
}
|
|
614
|
+
function writeMethodNotFoundError(id, method) {
|
|
615
|
+
writeErrorResponse(
|
|
616
|
+
id,
|
|
617
|
+
JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
618
|
+
`Method not found: ${method}`
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
function writeInternalError(id, message, data) {
|
|
622
|
+
writeErrorResponse(id, JSON_RPC_ERROR_CODES.INTERNAL_ERROR, message, data);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// src/modes/rpc/adapter.ts
|
|
626
|
+
var RPC_ERROR_TYPE_MAP = {
|
|
627
|
+
context_overflow: "context",
|
|
628
|
+
model_not_found: "model",
|
|
629
|
+
invalid_request: "context",
|
|
630
|
+
auth_failed: "auth",
|
|
631
|
+
payment_required: "payment",
|
|
632
|
+
access_denied: "model",
|
|
633
|
+
rate_limited: "rate_limit",
|
|
634
|
+
server_error: "server",
|
|
635
|
+
network_error: "network",
|
|
636
|
+
timeout: "network",
|
|
637
|
+
cancelled: "unknown",
|
|
638
|
+
unknown: "unknown"
|
|
639
|
+
};
|
|
640
|
+
var RPC_ERROR_CODE_MAP = {
|
|
641
|
+
context_overflow: 400,
|
|
642
|
+
model_not_found: 404,
|
|
643
|
+
invalid_request: 400,
|
|
644
|
+
auth_failed: 401,
|
|
645
|
+
payment_required: 402,
|
|
646
|
+
access_denied: 403,
|
|
647
|
+
rate_limited: 429,
|
|
648
|
+
server_error: 500,
|
|
649
|
+
network_error: 504,
|
|
650
|
+
timeout: 504,
|
|
651
|
+
cancelled: -32e3,
|
|
652
|
+
unknown: -32e3
|
|
653
|
+
};
|
|
654
|
+
var RPC_ERROR_ICON_MAP = {
|
|
655
|
+
context_overflow: "\u{1F4E6}",
|
|
656
|
+
// 📦
|
|
657
|
+
model_not_found: "\u{1F916}",
|
|
658
|
+
// 🤖
|
|
659
|
+
invalid_request: "\u{1F4E6}",
|
|
660
|
+
// 📦
|
|
661
|
+
auth_failed: "\u{1F510}",
|
|
662
|
+
// 🔐
|
|
663
|
+
payment_required: "\u{1F4B3}",
|
|
664
|
+
// 💳
|
|
665
|
+
access_denied: "\u{1F916}",
|
|
666
|
+
// 🤖
|
|
667
|
+
rate_limited: "\u23F1\uFE0F",
|
|
668
|
+
// ⏱️
|
|
669
|
+
server_error: "\u{1F527}",
|
|
670
|
+
// 🔧
|
|
671
|
+
network_error: "\u{1F310}",
|
|
672
|
+
// 🌐
|
|
673
|
+
timeout: "\u{1F310}",
|
|
674
|
+
// 🌐
|
|
675
|
+
cancelled: "\u26A0\uFE0F",
|
|
676
|
+
// ⚠️
|
|
677
|
+
unknown: "\u26A0\uFE0F"
|
|
678
|
+
// ⚠️
|
|
679
|
+
};
|
|
680
|
+
var RPCAdapter = class {
|
|
681
|
+
agent = null;
|
|
682
|
+
conversation = null;
|
|
683
|
+
imageManager = null;
|
|
684
|
+
sessionId = null;
|
|
685
|
+
currentTurnId = null;
|
|
686
|
+
turnStartTime = null;
|
|
687
|
+
currentMessageId = null;
|
|
688
|
+
currentMessageContent = "";
|
|
689
|
+
pendingPermissions = /* @__PURE__ */ new Map();
|
|
690
|
+
pendingDirectoryAccess = /* @__PURE__ */ new Map();
|
|
691
|
+
abortController = null;
|
|
692
|
+
status = "idle";
|
|
693
|
+
model = "";
|
|
694
|
+
workspace = "";
|
|
695
|
+
contextPercent = 0;
|
|
696
|
+
currentChangesBatchId = null;
|
|
697
|
+
// Enable preview mode for multi-file change batching (future: make configurable)
|
|
698
|
+
previewModeEnabled = true;
|
|
699
|
+
// MCP bridge: VS Code tools registered by the extension
|
|
700
|
+
vscodeTools = /* @__PURE__ */ new Map();
|
|
701
|
+
// MCP bridge: pending tool invocations waiting for extension response
|
|
702
|
+
pendingVscodeInvocations = /* @__PURE__ */ new Map();
|
|
703
|
+
// MCP server configurations from CLI config (set during initialization)
|
|
704
|
+
mcpServerConfigs = [];
|
|
705
|
+
// Cached vision support result (null = not yet checked)
|
|
706
|
+
visionSupported = null;
|
|
707
|
+
// Keepalive interval to prevent Chrome from killing the MV3 service worker
|
|
708
|
+
// during long turns with no traffic.
|
|
709
|
+
keepaliveInterval = null;
|
|
710
|
+
KEEPALIVE_MS = 15e3;
|
|
711
|
+
yoloRevertTimer = null;
|
|
712
|
+
yoloRevertGeneration = 0;
|
|
713
|
+
// Config reference for runtime settings changes
|
|
714
|
+
config = {};
|
|
715
|
+
/**
|
|
716
|
+
* Check if the current model supports vision/image inputs.
|
|
717
|
+
* Uses async OpenRouter API with pattern-matching fallback, cached for the session.
|
|
718
|
+
*/
|
|
719
|
+
async checkVisionSupport() {
|
|
720
|
+
if (this.visionSupported !== null) {
|
|
721
|
+
return this.visionSupported;
|
|
722
|
+
}
|
|
723
|
+
this.visionSupported = await modelSupportsImages(this.model);
|
|
724
|
+
return this.visionSupported;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Initialize the adapter with an agent instance
|
|
728
|
+
*/
|
|
729
|
+
initialize(agent, conversation, model, workspace, config, mcpServerConfigs) {
|
|
730
|
+
this.agent = agent;
|
|
731
|
+
this.conversation = conversation;
|
|
732
|
+
this.model = model;
|
|
733
|
+
this.workspace = workspace;
|
|
734
|
+
this.config = config ? { ...config } : {};
|
|
735
|
+
this.sessionId = generateId("session");
|
|
736
|
+
this.mcpServerConfigs = mcpServerConfigs ?? [];
|
|
737
|
+
this.imageManager = agent.getImageManager?.() ?? new ImageManager();
|
|
738
|
+
agent.setStatusListener((snapshot) => {
|
|
739
|
+
this.contextPercent = snapshot.contextPercent;
|
|
740
|
+
this.model = snapshot.model;
|
|
741
|
+
});
|
|
742
|
+
agent.setOutputListener((event) => {
|
|
743
|
+
this.handleAgentOutput(event);
|
|
744
|
+
});
|
|
745
|
+
writeNotification(RPC_NOTIFICATIONS.AGENT_START, {
|
|
746
|
+
sessionId: this.sessionId,
|
|
747
|
+
model: this.model,
|
|
748
|
+
workspace: this.workspace,
|
|
749
|
+
timestamp: createTimestamp(),
|
|
750
|
+
contextPercent: this.contextPercent
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Get current agent state
|
|
755
|
+
*/
|
|
756
|
+
getState() {
|
|
757
|
+
return {
|
|
758
|
+
status: this.status,
|
|
759
|
+
sessionId: this.sessionId,
|
|
760
|
+
model: this.model,
|
|
761
|
+
workspace: this.workspace,
|
|
762
|
+
contextPercent: this.contextPercent,
|
|
763
|
+
messageCount: this.conversation?.history().length ?? 0
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
async handleGoalGet() {
|
|
767
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
768
|
+
return new GoalManager(this.workspace).getSnapshot();
|
|
769
|
+
}
|
|
770
|
+
async handleGoalCreate(params) {
|
|
771
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
772
|
+
return new GoalManager(this.workspace).createGoal({
|
|
773
|
+
objective: params.objective,
|
|
774
|
+
tokenBudget: params.token_budget,
|
|
775
|
+
timeBudgetSeconds: params.time_budget_seconds,
|
|
776
|
+
minTokensBeforeWrapUp: params.min_tokens_before_wrap_up,
|
|
777
|
+
minTimeSecondsBeforeWrapUp: params.min_time_seconds_before_wrap_up
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
async handleGoalUpdate(params) {
|
|
781
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
782
|
+
return new GoalManager(this.workspace).updateGoal({
|
|
783
|
+
objective: params.objective,
|
|
784
|
+
status: parseRpcGoalStatus(params.status),
|
|
785
|
+
tokenBudget: params.token_budget,
|
|
786
|
+
timeBudgetSeconds: params.time_budget_seconds,
|
|
787
|
+
minTokensBeforeWrapUp: params.min_tokens_before_wrap_up,
|
|
788
|
+
minTimeSecondsBeforeWrapUp: params.min_time_seconds_before_wrap_up
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
async handleGoalClear() {
|
|
792
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
793
|
+
return new GoalManager(this.workspace).clearGoal();
|
|
794
|
+
}
|
|
795
|
+
async handleGoalQueue(params) {
|
|
796
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
797
|
+
const manager = new GoalManager(this.workspace);
|
|
798
|
+
return manager.enqueueGoal({
|
|
799
|
+
objective: params.objective,
|
|
800
|
+
source: "rpc",
|
|
801
|
+
tokenBudget: params.token_budget,
|
|
802
|
+
timeBudgetSeconds: params.time_budget_seconds,
|
|
803
|
+
minTokensBeforeWrapUp: params.min_tokens_before_wrap_up,
|
|
804
|
+
minTimeSecondsBeforeWrapUp: params.min_time_seconds_before_wrap_up
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
async handleGoalStartQueued() {
|
|
808
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
809
|
+
return new GoalManager(this.workspace).startQueuedGoal();
|
|
810
|
+
}
|
|
811
|
+
async handleGoalListTemplates() {
|
|
812
|
+
if (!this.isGoalFeatureEnabled()) return this.goalFeatureDisabledResult();
|
|
813
|
+
return new GoalManager(this.workspace).listTemplates();
|
|
814
|
+
}
|
|
815
|
+
isGoalFeatureEnabled() {
|
|
816
|
+
return isGoalFeatureEnabled(this.config);
|
|
817
|
+
}
|
|
818
|
+
goalFeatureDisabledResult() {
|
|
819
|
+
return { ok: false, message: GOAL_FEATURE_DISABLED_MESSAGE };
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Get message history
|
|
823
|
+
*/
|
|
824
|
+
getMessages(limit) {
|
|
825
|
+
if (!this.conversation) {
|
|
826
|
+
return [];
|
|
827
|
+
}
|
|
828
|
+
let messages = this.conversation.history();
|
|
829
|
+
if (limit && limit > 0) {
|
|
830
|
+
messages = messages.slice(-limit);
|
|
831
|
+
}
|
|
832
|
+
return messages.map((msg, index) => this.convertMessage(msg, index));
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Handle a prompt request
|
|
836
|
+
* Returns result for JSON-RPC response
|
|
837
|
+
*/
|
|
838
|
+
async handlePrompt(requestId, params) {
|
|
839
|
+
if (!this.agent) {
|
|
840
|
+
throw new Error("Agent not initialized");
|
|
841
|
+
}
|
|
842
|
+
if (this.status === "processing") {
|
|
843
|
+
throw new Error("Agent is already processing");
|
|
844
|
+
}
|
|
845
|
+
this.status = "processing";
|
|
846
|
+
this.abortController = new AbortController();
|
|
847
|
+
this.startKeepalive();
|
|
848
|
+
this.currentTurnId = generateId("turn");
|
|
849
|
+
this.turnStartTime = Date.now();
|
|
850
|
+
writeNotification(RPC_NOTIFICATIONS.TURN_START, {
|
|
851
|
+
turnId: this.currentTurnId,
|
|
852
|
+
timestamp: createTimestamp()
|
|
853
|
+
});
|
|
854
|
+
try {
|
|
855
|
+
const imagePlaceholders = [];
|
|
856
|
+
process.stderr.write(`[RPC] handlePrompt: images=${params.images?.length || 0}, hasImageManager=${!!this.imageManager}, model=${this.model}
|
|
857
|
+
`);
|
|
858
|
+
if (params.images && params.images.length > 0) {
|
|
859
|
+
const supportsVisionResult = await this.checkVisionSupport();
|
|
860
|
+
if (!supportsVisionResult) {
|
|
861
|
+
process.stderr.write(`[RPC] WARNING: Model '${this.model}' does not support vision. Images will not be processed.
|
|
862
|
+
`);
|
|
863
|
+
writeNotification(RPC_NOTIFICATIONS.ERROR, {
|
|
864
|
+
code: -32e3,
|
|
865
|
+
message: `Model '${this.model}' does not support image inputs. Please use a vision-capable model like claude-3.5-sonnet, gpt-4o, or gemini-1.5-pro.`,
|
|
866
|
+
recoverable: true,
|
|
867
|
+
timestamp: createTimestamp()
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (params.images && params.images.length > 0 && this.imageManager && await this.checkVisionSupport()) {
|
|
872
|
+
process.stderr.write(`[RPC] Processing ${params.images.length} images
|
|
873
|
+
`);
|
|
874
|
+
for (const img of params.images) {
|
|
875
|
+
try {
|
|
876
|
+
process.stderr.write(`[RPC] Image: mimeType=${img.mimeType}, dataLength=${img.data?.length || 0}
|
|
877
|
+
`);
|
|
878
|
+
if (!isValidImageMimeType(img.mimeType)) {
|
|
879
|
+
process.stderr.write(`[RPC] Invalid MIME type: ${img.mimeType}
|
|
880
|
+
`);
|
|
881
|
+
writeNotification(RPC_NOTIFICATIONS.ERROR, {
|
|
882
|
+
code: -32602,
|
|
883
|
+
// Invalid params
|
|
884
|
+
message: `Invalid image MIME type: ${img.mimeType}`,
|
|
885
|
+
recoverable: true,
|
|
886
|
+
timestamp: createTimestamp()
|
|
887
|
+
});
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
const data = Buffer.from(img.data, "base64");
|
|
891
|
+
process.stderr.write(`[RPC] Image decoded: ${data.length} bytes
|
|
892
|
+
`);
|
|
893
|
+
if (data.length > MAX_IMAGE_SIZE) {
|
|
894
|
+
writeNotification(RPC_NOTIFICATIONS.ERROR, {
|
|
895
|
+
code: -32602,
|
|
896
|
+
message: `Image too large: ${Math.round(data.length / 1024 / 1024)}MB (max: ${Math.round(MAX_IMAGE_SIZE / 1024 / 1024)}MB)`,
|
|
897
|
+
recoverable: true,
|
|
898
|
+
timestamp: createTimestamp()
|
|
899
|
+
});
|
|
900
|
+
continue;
|
|
901
|
+
}
|
|
902
|
+
const id = this.imageManager.add(data, img.mimeType, img.filename);
|
|
903
|
+
const placeholder = this.imageManager.formatPlaceholder(id);
|
|
904
|
+
imagePlaceholders.push(placeholder);
|
|
905
|
+
} catch (error) {
|
|
906
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
907
|
+
writeNotification(RPC_NOTIFICATIONS.ERROR, {
|
|
908
|
+
code: -32e3,
|
|
909
|
+
message: `Failed to process image: ${message}`,
|
|
910
|
+
recoverable: true,
|
|
911
|
+
timestamp: createTimestamp()
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
let instruction = params.message;
|
|
917
|
+
const isSlashCmd = this.agent.isSlashCommand(instruction);
|
|
918
|
+
if (!isSlashCmd) {
|
|
919
|
+
if (imagePlaceholders.length > 0) {
|
|
920
|
+
process.stderr.write(`[RPC] Image placeholders: ${imagePlaceholders.join(", ")}
|
|
921
|
+
`);
|
|
922
|
+
instruction = `${imagePlaceholders.join(" ")}
|
|
923
|
+
|
|
924
|
+
${instruction}`;
|
|
925
|
+
} else if (params.images && params.images.length > 0) {
|
|
926
|
+
process.stderr.write(`[RPC] WARNING: Images provided but no placeholders generated!
|
|
927
|
+
`);
|
|
928
|
+
}
|
|
929
|
+
if (params.context?.selection) {
|
|
930
|
+
const sel = params.context.selection;
|
|
931
|
+
instruction = `${instruction}
|
|
932
|
+
|
|
933
|
+
Context from ${sel.file} (lines ${sel.startLine}-${sel.endLine}):
|
|
934
|
+
\`\`\`
|
|
935
|
+
${sel.text}
|
|
936
|
+
\`\`\``;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
this.currentMessageId = generateId("msg");
|
|
940
|
+
this.currentMessageContent = "";
|
|
941
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_START, {
|
|
942
|
+
messageId: this.currentMessageId,
|
|
943
|
+
role: "assistant",
|
|
944
|
+
timestamp: createTimestamp()
|
|
945
|
+
});
|
|
946
|
+
let success = false;
|
|
947
|
+
try {
|
|
948
|
+
process.stderr.write(`[RPC DEBUG] Executing instruction: ${instruction.substring(0, 100)}
|
|
949
|
+
`);
|
|
950
|
+
if (isSlashCmd) {
|
|
951
|
+
const { command, args } = this.agent.parseSlashCommand(instruction);
|
|
952
|
+
process.stderr.write(`[RPC DEBUG] Handling slash command: ${command}, args: ${JSON.stringify(args)}
|
|
953
|
+
`);
|
|
954
|
+
if (this.agent.isSlashCommandSupported(command)) {
|
|
955
|
+
const result = await this.agent.handleSlashCommand(command, args);
|
|
956
|
+
if (result !== null) {
|
|
957
|
+
this.currentMessageContent = result;
|
|
958
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
959
|
+
messageId: this.currentMessageId,
|
|
960
|
+
delta: result,
|
|
961
|
+
timestamp: createTimestamp()
|
|
962
|
+
});
|
|
963
|
+
} else {
|
|
964
|
+
this.currentMessageContent = `Command ${command} executed.`;
|
|
965
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
966
|
+
messageId: this.currentMessageId,
|
|
967
|
+
delta: this.currentMessageContent,
|
|
968
|
+
timestamp: createTimestamp()
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
success = true;
|
|
972
|
+
} else {
|
|
973
|
+
this.currentMessageContent = `Unknown command: ${command}. Type /help for available commands.`;
|
|
974
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
975
|
+
messageId: this.currentMessageId,
|
|
976
|
+
delta: this.currentMessageContent,
|
|
977
|
+
timestamp: createTimestamp()
|
|
978
|
+
});
|
|
979
|
+
success = false;
|
|
980
|
+
}
|
|
981
|
+
} else {
|
|
982
|
+
const fileManager = this.agent.getFileManager();
|
|
983
|
+
process.stderr.write(`[RPC DEBUG] previewModeEnabled=${this.previewModeEnabled}, hasFileManager=${!!fileManager}
|
|
984
|
+
`);
|
|
985
|
+
if (this.previewModeEnabled && fileManager) {
|
|
986
|
+
this.currentChangesBatchId = generateId("changes");
|
|
987
|
+
process.stderr.write(`[RPC DEBUG] Entering preview mode with batchId=${this.currentChangesBatchId}
|
|
988
|
+
`);
|
|
989
|
+
this.emitChangesBatchStart(this.currentChangesBatchId);
|
|
990
|
+
fileManager.enterPreviewMode(this.currentChangesBatchId, (change) => {
|
|
991
|
+
this.emitChangesBatchUpdate(this.currentChangesBatchId, {
|
|
992
|
+
id: change.id,
|
|
993
|
+
filePath: change.filePath,
|
|
994
|
+
changeType: change.changeType,
|
|
995
|
+
originalContent: change.originalContent,
|
|
996
|
+
proposedContent: change.proposedContent,
|
|
997
|
+
description: change.description,
|
|
998
|
+
toolId: change.toolId,
|
|
999
|
+
toolName: change.toolName
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
try {
|
|
1004
|
+
success = await this.agent.runInstruction(instruction);
|
|
1005
|
+
} finally {
|
|
1006
|
+
if (this.previewModeEnabled && fileManager && this.currentChangesBatchId) {
|
|
1007
|
+
const pendingChanges = fileManager.getPendingChanges();
|
|
1008
|
+
process.stderr.write(`[RPC DEBUG] Turn finished, pendingChanges=${pendingChanges.length}, files=${pendingChanges.map((c) => c.filePath).join(", ")}
|
|
1009
|
+
`);
|
|
1010
|
+
this.emitChangesBatchEnd(this.currentChangesBatchId, pendingChanges.length);
|
|
1011
|
+
if (pendingChanges.length === 0) {
|
|
1012
|
+
fileManager.exitPreviewMode();
|
|
1013
|
+
}
|
|
1014
|
+
this.currentChangesBatchId = null;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
process.stderr.write(`[RPC DEBUG] Instruction completed, success=${success}, content length=${this.currentMessageContent.length}
|
|
1019
|
+
`);
|
|
1020
|
+
const turnDuration = this.turnStartTime ? Date.now() - this.turnStartTime : 0;
|
|
1021
|
+
try {
|
|
1022
|
+
const hookManager = this.agent?.getHookManager?.();
|
|
1023
|
+
process.stderr.write(`[RPC DEBUG] Hook execution: hookManager=${!!hookManager}
|
|
1024
|
+
`);
|
|
1025
|
+
if (hookManager) {
|
|
1026
|
+
const snapshot2 = this.agent?.getStatusSnapshot();
|
|
1027
|
+
process.stderr.write(`[RPC DEBUG] Executing stop hooks...
|
|
1028
|
+
`);
|
|
1029
|
+
await hookManager.executeHooks("stop", {
|
|
1030
|
+
sessionId: this.sessionId || void 0,
|
|
1031
|
+
turnDuration,
|
|
1032
|
+
tokensUsed: snapshot2?.tokensUsed ?? 0,
|
|
1033
|
+
tokensUsageStatus: snapshot2?.tokensUsageStatus
|
|
1034
|
+
});
|
|
1035
|
+
process.stderr.write(`[RPC DEBUG] Stop hooks completed
|
|
1036
|
+
`);
|
|
1037
|
+
this.emitHookStop(
|
|
1038
|
+
snapshot2?.tokensUsed ?? 0,
|
|
1039
|
+
0,
|
|
1040
|
+
// toolCallsCount - not tracked per turn currently
|
|
1041
|
+
turnDuration,
|
|
1042
|
+
snapshot2?.tokensUsageStatus
|
|
1043
|
+
);
|
|
1044
|
+
process.stderr.write(`[RPC DEBUG] HOOK_STOP emitted
|
|
1045
|
+
`);
|
|
1046
|
+
}
|
|
1047
|
+
} catch (hookErr) {
|
|
1048
|
+
const hookErrMsg = hookErr instanceof Error ? hookErr.message : String(hookErr);
|
|
1049
|
+
process.stderr.write(`[RPC DEBUG] Hook execution error (non-blocking): ${hookErrMsg}
|
|
1050
|
+
`);
|
|
1051
|
+
}
|
|
1052
|
+
} catch (err) {
|
|
1053
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1054
|
+
const errorStack = err instanceof Error ? err.stack : "";
|
|
1055
|
+
process.stderr.write(`[RPC DEBUG] Error during runInstruction: ${errorMessage}
|
|
1056
|
+
`);
|
|
1057
|
+
process.stderr.write(`[RPC DEBUG] Stack: ${errorStack}
|
|
1058
|
+
`);
|
|
1059
|
+
writeNotification(RPC_NOTIFICATIONS.ERROR, {
|
|
1060
|
+
code: -32e3,
|
|
1061
|
+
message: errorMessage,
|
|
1062
|
+
recoverable: true,
|
|
1063
|
+
timestamp: createTimestamp()
|
|
1064
|
+
});
|
|
1065
|
+
success = false;
|
|
1066
|
+
}
|
|
1067
|
+
process.stderr.write(`[RPC DEBUG] Emitting MESSAGE_END, messageId=${this.currentMessageId}
|
|
1068
|
+
`);
|
|
1069
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_END, {
|
|
1070
|
+
messageId: this.currentMessageId,
|
|
1071
|
+
content: this.currentMessageContent,
|
|
1072
|
+
timestamp: createTimestamp()
|
|
1073
|
+
});
|
|
1074
|
+
process.stderr.write(`[RPC DEBUG] MESSAGE_END emitted successfully
|
|
1075
|
+
`);
|
|
1076
|
+
const durationMs = this.turnStartTime ? Date.now() - this.turnStartTime : void 0;
|
|
1077
|
+
const snapshot = this.agent?.getStatusSnapshot();
|
|
1078
|
+
process.stderr.write(`[RPC DEBUG] Emitting TURN_END, turnId=${this.currentTurnId}
|
|
1079
|
+
`);
|
|
1080
|
+
writeNotification(RPC_NOTIFICATIONS.TURN_END, {
|
|
1081
|
+
turnId: this.currentTurnId,
|
|
1082
|
+
timestamp: createTimestamp(),
|
|
1083
|
+
contextPercent: this.contextPercent,
|
|
1084
|
+
tokensUsed: snapshot?.tokensUsed,
|
|
1085
|
+
tokensUsageStatus: snapshot?.tokensUsageStatus,
|
|
1086
|
+
durationMs
|
|
1087
|
+
});
|
|
1088
|
+
process.stderr.write(`[RPC DEBUG] TURN_END emitted successfully
|
|
1089
|
+
`);
|
|
1090
|
+
this.stopKeepalive();
|
|
1091
|
+
this.status = "idle";
|
|
1092
|
+
this.currentTurnId = null;
|
|
1093
|
+
this.turnStartTime = null;
|
|
1094
|
+
this.currentMessageId = null;
|
|
1095
|
+
this.abortController = null;
|
|
1096
|
+
return { success };
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1099
|
+
process.stderr.write(`[RPC DEBUG] Outer catch - error: ${errorMsg}
|
|
1100
|
+
`);
|
|
1101
|
+
if (this.currentMessageId) {
|
|
1102
|
+
process.stderr.write(`[RPC DEBUG] Emitting MESSAGE_END from outer catch, messageId=${this.currentMessageId}
|
|
1103
|
+
`);
|
|
1104
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_END, {
|
|
1105
|
+
messageId: this.currentMessageId,
|
|
1106
|
+
content: this.currentMessageContent,
|
|
1107
|
+
timestamp: createTimestamp()
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
const durationMs = this.turnStartTime ? Date.now() - this.turnStartTime : void 0;
|
|
1111
|
+
const snapshot = this.agent?.getStatusSnapshot();
|
|
1112
|
+
process.stderr.write(`[RPC DEBUG] Emitting TURN_END from outer catch, turnId=${this.currentTurnId}
|
|
1113
|
+
`);
|
|
1114
|
+
writeNotification(RPC_NOTIFICATIONS.TURN_END, {
|
|
1115
|
+
turnId: this.currentTurnId,
|
|
1116
|
+
timestamp: createTimestamp(),
|
|
1117
|
+
contextPercent: this.contextPercent,
|
|
1118
|
+
tokensUsed: snapshot?.tokensUsed,
|
|
1119
|
+
tokensUsageStatus: snapshot?.tokensUsageStatus,
|
|
1120
|
+
durationMs
|
|
1121
|
+
});
|
|
1122
|
+
this.stopKeepalive();
|
|
1123
|
+
this.status = "idle";
|
|
1124
|
+
this.currentTurnId = null;
|
|
1125
|
+
this.turnStartTime = null;
|
|
1126
|
+
this.currentMessageId = null;
|
|
1127
|
+
this.abortController = null;
|
|
1128
|
+
throw error;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Handle abort request (can be notification with null id for instant abort)
|
|
1133
|
+
*/
|
|
1134
|
+
handleAbort(_requestId) {
|
|
1135
|
+
process.stderr.write(`[RPC] handleAbort called, abortController=${!!this.abortController}
|
|
1136
|
+
`);
|
|
1137
|
+
for (const [permId, pending] of this.pendingPermissions) {
|
|
1138
|
+
process.stderr.write(`[RPC] Clearing pending permission ${permId} due to abort
|
|
1139
|
+
`);
|
|
1140
|
+
if (pending.ackTimeout) clearTimeout(pending.ackTimeout);
|
|
1141
|
+
if (pending.responseTimeout) clearTimeout(pending.responseTimeout);
|
|
1142
|
+
pending.resolve({ decision: "deny_once" });
|
|
1143
|
+
}
|
|
1144
|
+
this.pendingPermissions.clear();
|
|
1145
|
+
if (this.abortController) {
|
|
1146
|
+
this.abortController.abort();
|
|
1147
|
+
this.stopKeepalive();
|
|
1148
|
+
this.status = "idle";
|
|
1149
|
+
if (this.currentMessageId) {
|
|
1150
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_END, {
|
|
1151
|
+
messageId: this.currentMessageId,
|
|
1152
|
+
content: this.currentMessageContent,
|
|
1153
|
+
// No marker - UI handles display
|
|
1154
|
+
aborted: true,
|
|
1155
|
+
timestamp: createTimestamp()
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
if (this.currentTurnId) {
|
|
1159
|
+
const durationMs = this.turnStartTime ? Date.now() - this.turnStartTime : void 0;
|
|
1160
|
+
const snapshot = this.agent?.getStatusSnapshot();
|
|
1161
|
+
writeNotification(RPC_NOTIFICATIONS.TURN_END, {
|
|
1162
|
+
turnId: this.currentTurnId,
|
|
1163
|
+
timestamp: createTimestamp(),
|
|
1164
|
+
contextPercent: this.contextPercent,
|
|
1165
|
+
tokensUsed: snapshot?.tokensUsed,
|
|
1166
|
+
tokensUsageStatus: snapshot?.tokensUsageStatus,
|
|
1167
|
+
durationMs
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
this.currentTurnId = null;
|
|
1171
|
+
this.turnStartTime = null;
|
|
1172
|
+
this.currentMessageId = null;
|
|
1173
|
+
this.currentMessageContent = "";
|
|
1174
|
+
this.abortController = null;
|
|
1175
|
+
return { success: true };
|
|
1176
|
+
}
|
|
1177
|
+
return { success: false };
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Handle reset request
|
|
1181
|
+
*/
|
|
1182
|
+
async handleReset(_requestId) {
|
|
1183
|
+
if (this.agent && this.conversation) {
|
|
1184
|
+
try {
|
|
1185
|
+
const { extractAndSaveSessionMemories } = await import("./extractSessionMemories-A2JX5WJ2.js");
|
|
1186
|
+
await extractAndSaveSessionMemories({
|
|
1187
|
+
llm: this.agent.getLlmProvider(),
|
|
1188
|
+
memoryManager: this.agent.getMemoryManager(),
|
|
1189
|
+
conversationHistory: this.conversation.history(),
|
|
1190
|
+
workspaceRoot: this.workspace
|
|
1191
|
+
});
|
|
1192
|
+
} catch {
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
if (this.conversation) {
|
|
1196
|
+
const history = this.conversation.history();
|
|
1197
|
+
const systemPrompt = history.find((m) => m.role === "system")?.content ?? "";
|
|
1198
|
+
this.conversation.reset(systemPrompt);
|
|
1199
|
+
}
|
|
1200
|
+
this.imageManager?.clear();
|
|
1201
|
+
this.stopKeepalive();
|
|
1202
|
+
this.sessionId = generateId("session");
|
|
1203
|
+
this.status = "idle";
|
|
1204
|
+
this.currentTurnId = null;
|
|
1205
|
+
this.currentMessageId = null;
|
|
1206
|
+
this.currentMessageContent = "";
|
|
1207
|
+
writeNotification(RPC_NOTIFICATIONS.AGENT_START, {
|
|
1208
|
+
sessionId: this.sessionId,
|
|
1209
|
+
model: this.model,
|
|
1210
|
+
workspace: this.workspace,
|
|
1211
|
+
timestamp: createTimestamp()
|
|
1212
|
+
});
|
|
1213
|
+
return { sessionId: this.sessionId };
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Handle get_state request
|
|
1217
|
+
*/
|
|
1218
|
+
handleGetState(_requestId) {
|
|
1219
|
+
return this.getState();
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Handle get_messages request
|
|
1223
|
+
*/
|
|
1224
|
+
handleGetMessages(requestId, limit) {
|
|
1225
|
+
const messages = this.getMessages(limit);
|
|
1226
|
+
return { messages };
|
|
1227
|
+
}
|
|
1228
|
+
async handleBrowserHandoffCreate(_requestId, params) {
|
|
1229
|
+
const session = this.agent?.getSessionManager?.().getCurrentSession?.();
|
|
1230
|
+
if (!session) {
|
|
1231
|
+
throw new Error("No active session available for browser handoff.");
|
|
1232
|
+
}
|
|
1233
|
+
return createBrowserHandoff({
|
|
1234
|
+
sessionId: session.metadata.sessionId,
|
|
1235
|
+
workspaceRoot: session.metadata.projectPath,
|
|
1236
|
+
extensionId: params?.extensionId,
|
|
1237
|
+
installUrl: params?.installUrl
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
async handleBrowserHandoffAttach(_requestId, params) {
|
|
1241
|
+
const handoff = await attachBrowserHandoff(params.token);
|
|
1242
|
+
if (!handoff) {
|
|
1243
|
+
return { success: false };
|
|
1244
|
+
}
|
|
1245
|
+
if (!this.agent) {
|
|
1246
|
+
throw new Error("Agent not initialized");
|
|
1247
|
+
}
|
|
1248
|
+
const attached = await this.agent.attachSession(handoff.sessionId);
|
|
1249
|
+
this.sessionId = attached.sessionId;
|
|
1250
|
+
this.stopKeepalive();
|
|
1251
|
+
this.stopKeepalive();
|
|
1252
|
+
this.workspace = attached.workspaceRoot;
|
|
1253
|
+
this.model = attached.model;
|
|
1254
|
+
this.status = "idle";
|
|
1255
|
+
return {
|
|
1256
|
+
success: true,
|
|
1257
|
+
sessionId: attached.sessionId,
|
|
1258
|
+
workspaceRoot: attached.workspaceRoot,
|
|
1259
|
+
messageCount: attached.messageCount
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
async handleBrowserHandoffAttachLatest(_requestId, _params) {
|
|
1263
|
+
const handoff = await attachLatestBrowserHandoff();
|
|
1264
|
+
if (!handoff) {
|
|
1265
|
+
return { success: false };
|
|
1266
|
+
}
|
|
1267
|
+
if (!this.agent) {
|
|
1268
|
+
throw new Error("Agent not initialized");
|
|
1269
|
+
}
|
|
1270
|
+
const attached = await this.agent.attachSession(handoff.sessionId);
|
|
1271
|
+
this.stopKeepalive();
|
|
1272
|
+
this.sessionId = attached.sessionId;
|
|
1273
|
+
this.workspace = attached.workspaceRoot;
|
|
1274
|
+
this.model = attached.model;
|
|
1275
|
+
this.status = "idle";
|
|
1276
|
+
return {
|
|
1277
|
+
success: true,
|
|
1278
|
+
sessionId: attached.sessionId,
|
|
1279
|
+
workspaceRoot: attached.workspaceRoot,
|
|
1280
|
+
messageCount: attached.messageCount
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Handle permission response from client
|
|
1285
|
+
*/
|
|
1286
|
+
handlePermissionResponse(requestId, permRequestId, decision) {
|
|
1287
|
+
process.stderr.write(`[RPC] handlePermissionResponse called: permRequestId=${permRequestId}, allowed=${decision}, pending keys=${Array.from(this.pendingPermissions.keys()).join(",")}
|
|
1288
|
+
`);
|
|
1289
|
+
const pending = this.pendingPermissions.get(permRequestId);
|
|
1290
|
+
if (pending) {
|
|
1291
|
+
const normalized = normalizePermissionPromptResponse(decision);
|
|
1292
|
+
process.stderr.write(`[RPC] Found pending permission, resolving with allowed=${normalized.decision}
|
|
1293
|
+
`);
|
|
1294
|
+
if (pending.ackTimeout) {
|
|
1295
|
+
clearTimeout(pending.ackTimeout);
|
|
1296
|
+
}
|
|
1297
|
+
if (pending.responseTimeout) {
|
|
1298
|
+
clearTimeout(pending.responseTimeout);
|
|
1299
|
+
}
|
|
1300
|
+
this.pendingPermissions.delete(permRequestId);
|
|
1301
|
+
pending.resolve(normalized);
|
|
1302
|
+
this.status = "processing";
|
|
1303
|
+
process.stderr.write(`[RPC] Permission resolved, status set to processing
|
|
1304
|
+
`);
|
|
1305
|
+
return { success: true };
|
|
1306
|
+
}
|
|
1307
|
+
process.stderr.write(`[RPC] Permission response for unknown request ${permRequestId}
|
|
1308
|
+
`);
|
|
1309
|
+
return { success: false };
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Request permission from client (called from agent's confirmDangerousAction)
|
|
1313
|
+
* Uses two-phase timeout:
|
|
1314
|
+
* - Phase 1: 30s to receive acknowledgment from extension
|
|
1315
|
+
* - Phase 2: 1 hour for user to respond after ack received
|
|
1316
|
+
*/
|
|
1317
|
+
async requestPermission(tool, description, context) {
|
|
1318
|
+
const permRequestId = generateId("perm");
|
|
1319
|
+
this.status = "waiting_permission";
|
|
1320
|
+
process.stderr.write(`[RPC] requestPermission: tool=${tool}, permRequestId=${permRequestId}
|
|
1321
|
+
`);
|
|
1322
|
+
writeNotification(RPC_NOTIFICATIONS.PERMISSION_REQUEST, {
|
|
1323
|
+
requestId: permRequestId,
|
|
1324
|
+
tool,
|
|
1325
|
+
description,
|
|
1326
|
+
context,
|
|
1327
|
+
options: [
|
|
1328
|
+
"allow_once",
|
|
1329
|
+
"deny_once",
|
|
1330
|
+
"allow_session",
|
|
1331
|
+
"deny_session",
|
|
1332
|
+
"allow_always_project",
|
|
1333
|
+
"allow_always_user",
|
|
1334
|
+
"deny_always_project",
|
|
1335
|
+
"deny_always_user",
|
|
1336
|
+
"alternative"
|
|
1337
|
+
],
|
|
1338
|
+
timestamp: createTimestamp()
|
|
1339
|
+
});
|
|
1340
|
+
return new Promise((resolve, reject) => {
|
|
1341
|
+
const ackTimeout = setTimeout(() => {
|
|
1342
|
+
this.pendingPermissions.delete(permRequestId);
|
|
1343
|
+
this.status = "processing";
|
|
1344
|
+
process.stderr.write(`[RPC] Permission ack timeout for ${permRequestId}
|
|
1345
|
+
`);
|
|
1346
|
+
resolve({ decision: "deny_once" });
|
|
1347
|
+
}, 3e4);
|
|
1348
|
+
this.pendingPermissions.set(permRequestId, {
|
|
1349
|
+
requestId: permRequestId,
|
|
1350
|
+
resolve,
|
|
1351
|
+
reject,
|
|
1352
|
+
ackTimeout,
|
|
1353
|
+
responseTimeout: null,
|
|
1354
|
+
acknowledged: false
|
|
1355
|
+
});
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Handle acknowledgment from client that permission UI is shown
|
|
1360
|
+
* Extends timeout since we know extension is alive and user is deciding
|
|
1361
|
+
*/
|
|
1362
|
+
handlePermissionAcknowledged(permRequestId) {
|
|
1363
|
+
const pending = this.pendingPermissions.get(permRequestId);
|
|
1364
|
+
if (!pending) {
|
|
1365
|
+
process.stderr.write(`[RPC] Permission ack for unknown request ${permRequestId}
|
|
1366
|
+
`);
|
|
1367
|
+
return { success: false };
|
|
1368
|
+
}
|
|
1369
|
+
if (pending.acknowledged) {
|
|
1370
|
+
return { success: true };
|
|
1371
|
+
}
|
|
1372
|
+
if (pending.ackTimeout) {
|
|
1373
|
+
clearTimeout(pending.ackTimeout);
|
|
1374
|
+
pending.ackTimeout = null;
|
|
1375
|
+
}
|
|
1376
|
+
pending.acknowledged = true;
|
|
1377
|
+
pending.responseTimeout = setTimeout(() => {
|
|
1378
|
+
this.pendingPermissions.delete(permRequestId);
|
|
1379
|
+
this.status = "processing";
|
|
1380
|
+
process.stderr.write(`[RPC] Permission response timeout for ${permRequestId} (1 hour)
|
|
1381
|
+
`);
|
|
1382
|
+
pending.resolve({ decision: "deny_once" });
|
|
1383
|
+
}, 36e5);
|
|
1384
|
+
process.stderr.write(`[RPC] Permission acknowledged for ${permRequestId}
|
|
1385
|
+
`);
|
|
1386
|
+
return { success: true };
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Request directory access from client (called from agent's requestDirectoryAccess)
|
|
1390
|
+
* Uses two-phase timeout similar to permission requests:
|
|
1391
|
+
* - Phase 1: 30s to receive acknowledgment from extension
|
|
1392
|
+
* - Phase 2: 1 hour for user to respond after ack received
|
|
1393
|
+
*/
|
|
1394
|
+
async requestDirectoryAccess(dirPath, reason) {
|
|
1395
|
+
const requestId = generateId("dir");
|
|
1396
|
+
this.status = "waiting_permission";
|
|
1397
|
+
process.stderr.write(`[RPC] requestDirectoryAccess: path=${dirPath}, requestId=${requestId}
|
|
1398
|
+
`);
|
|
1399
|
+
writeNotification(RPC_NOTIFICATIONS.DIRECTORY_ACCESS_REQUEST, {
|
|
1400
|
+
requestId,
|
|
1401
|
+
path: dirPath,
|
|
1402
|
+
reason,
|
|
1403
|
+
timestamp: createTimestamp()
|
|
1404
|
+
});
|
|
1405
|
+
return new Promise((resolve, reject) => {
|
|
1406
|
+
const ackTimeout = setTimeout(() => {
|
|
1407
|
+
this.pendingDirectoryAccess.delete(requestId);
|
|
1408
|
+
this.status = "processing";
|
|
1409
|
+
process.stderr.write(`[RPC] Directory access ack timeout for ${requestId}
|
|
1410
|
+
`);
|
|
1411
|
+
resolve(void 0);
|
|
1412
|
+
}, 3e4);
|
|
1413
|
+
this.pendingDirectoryAccess.set(requestId, {
|
|
1414
|
+
requestId,
|
|
1415
|
+
path: dirPath,
|
|
1416
|
+
resolve,
|
|
1417
|
+
reject,
|
|
1418
|
+
ackTimeout,
|
|
1419
|
+
responseTimeout: null,
|
|
1420
|
+
acknowledged: false
|
|
1421
|
+
});
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Handle acknowledgment from client that directory access UI is shown
|
|
1426
|
+
*/
|
|
1427
|
+
handleDirectoryAccessAcknowledged(requestId) {
|
|
1428
|
+
const pending = this.pendingDirectoryAccess.get(requestId);
|
|
1429
|
+
if (!pending) {
|
|
1430
|
+
process.stderr.write(`[RPC] Directory access ack for unknown request ${requestId}
|
|
1431
|
+
`);
|
|
1432
|
+
return { success: false };
|
|
1433
|
+
}
|
|
1434
|
+
if (pending.acknowledged) {
|
|
1435
|
+
return { success: true };
|
|
1436
|
+
}
|
|
1437
|
+
if (pending.ackTimeout) {
|
|
1438
|
+
clearTimeout(pending.ackTimeout);
|
|
1439
|
+
pending.ackTimeout = null;
|
|
1440
|
+
}
|
|
1441
|
+
pending.acknowledged = true;
|
|
1442
|
+
pending.responseTimeout = setTimeout(() => {
|
|
1443
|
+
this.pendingDirectoryAccess.delete(requestId);
|
|
1444
|
+
this.status = "processing";
|
|
1445
|
+
process.stderr.write(`[RPC] Directory access response timeout for ${requestId} (1 hour)
|
|
1446
|
+
`);
|
|
1447
|
+
pending.resolve(void 0);
|
|
1448
|
+
}, 36e5);
|
|
1449
|
+
process.stderr.write(`[RPC] Directory access acknowledged for ${requestId}
|
|
1450
|
+
`);
|
|
1451
|
+
return { success: true };
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Handle directory access response from client
|
|
1455
|
+
*/
|
|
1456
|
+
handleDirectoryAccessResponse(requestId, granted) {
|
|
1457
|
+
process.stderr.write(`[RPC] handleDirectoryAccessResponse: requestId=${requestId}, granted=${granted}
|
|
1458
|
+
`);
|
|
1459
|
+
const pending = this.pendingDirectoryAccess.get(requestId);
|
|
1460
|
+
if (pending) {
|
|
1461
|
+
if (pending.ackTimeout) {
|
|
1462
|
+
clearTimeout(pending.ackTimeout);
|
|
1463
|
+
}
|
|
1464
|
+
if (pending.responseTimeout) {
|
|
1465
|
+
clearTimeout(pending.responseTimeout);
|
|
1466
|
+
}
|
|
1467
|
+
this.pendingDirectoryAccess.delete(requestId);
|
|
1468
|
+
pending.resolve(granted ? pending.path : void 0);
|
|
1469
|
+
this.status = "processing";
|
|
1470
|
+
process.stderr.write(`[RPC] Directory access resolved, status set to processing
|
|
1471
|
+
`);
|
|
1472
|
+
return { success: true };
|
|
1473
|
+
}
|
|
1474
|
+
process.stderr.write(`[RPC] Directory access response for unknown request ${requestId}
|
|
1475
|
+
`);
|
|
1476
|
+
return { success: false };
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Emit tool execution start notification
|
|
1480
|
+
*/
|
|
1481
|
+
emitToolStart(toolName, args) {
|
|
1482
|
+
const toolId = generateId("tool");
|
|
1483
|
+
writeNotification(RPC_NOTIFICATIONS.TOOL_START, {
|
|
1484
|
+
toolId,
|
|
1485
|
+
toolName,
|
|
1486
|
+
args,
|
|
1487
|
+
timestamp: createTimestamp()
|
|
1488
|
+
});
|
|
1489
|
+
return toolId;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Emit tool execution update notification (streaming output)
|
|
1493
|
+
*/
|
|
1494
|
+
emitToolUpdate(toolId, chunk) {
|
|
1495
|
+
writeNotification(RPC_NOTIFICATIONS.TOOL_UPDATE, {
|
|
1496
|
+
toolId,
|
|
1497
|
+
output: chunk.data,
|
|
1498
|
+
stream: chunk.stream,
|
|
1499
|
+
timestamp: createTimestamp()
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Emit tool execution end notification
|
|
1504
|
+
*/
|
|
1505
|
+
emitToolEnd(toolId, toolName, success, output, error) {
|
|
1506
|
+
writeNotification(RPC_NOTIFICATIONS.TOOL_END, {
|
|
1507
|
+
toolId,
|
|
1508
|
+
toolName,
|
|
1509
|
+
success,
|
|
1510
|
+
output,
|
|
1511
|
+
error,
|
|
1512
|
+
timestamp: createTimestamp()
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Emit message update notification (streaming content)
|
|
1517
|
+
*/
|
|
1518
|
+
emitMessageUpdate(delta, thought) {
|
|
1519
|
+
this.currentMessageContent += delta;
|
|
1520
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
1521
|
+
messageId: this.currentMessageId,
|
|
1522
|
+
delta,
|
|
1523
|
+
thought,
|
|
1524
|
+
timestamp: createTimestamp()
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
// ============================================================================
|
|
1528
|
+
// Multi-File Change Preview Methods
|
|
1529
|
+
// ============================================================================
|
|
1530
|
+
/**
|
|
1531
|
+
* Emit changes batch start notification
|
|
1532
|
+
*/
|
|
1533
|
+
emitChangesBatchStart(batchId) {
|
|
1534
|
+
process.stderr.write(`[RPC DEBUG] emitChangesBatchStart: batchId=${batchId}
|
|
1535
|
+
`);
|
|
1536
|
+
writeNotification(RPC_NOTIFICATIONS.CHANGES_BATCH_START, {
|
|
1537
|
+
batchId,
|
|
1538
|
+
turnId: this.currentTurnId ?? "",
|
|
1539
|
+
timestamp: createTimestamp()
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Emit changes batch update notification (individual file change)
|
|
1544
|
+
*/
|
|
1545
|
+
emitChangesBatchUpdate(batchId, change) {
|
|
1546
|
+
process.stderr.write(`[RPC DEBUG] emitChangesBatchUpdate: batchId=${batchId}, changeId=${change.id}, file=${change.filePath}
|
|
1547
|
+
`);
|
|
1548
|
+
writeNotification(RPC_NOTIFICATIONS.CHANGES_BATCH_UPDATE, {
|
|
1549
|
+
batchId,
|
|
1550
|
+
change,
|
|
1551
|
+
timestamp: createTimestamp()
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Emit changes batch end notification
|
|
1556
|
+
*/
|
|
1557
|
+
emitChangesBatchEnd(batchId, changeCount) {
|
|
1558
|
+
process.stderr.write(`[RPC DEBUG] emitChangesBatchEnd: batchId=${batchId}, changeCount=${changeCount}
|
|
1559
|
+
`);
|
|
1560
|
+
writeNotification(RPC_NOTIFICATIONS.CHANGES_BATCH_END, {
|
|
1561
|
+
batchId,
|
|
1562
|
+
changeCount,
|
|
1563
|
+
timestamp: createTimestamp()
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
// ============================================================================
|
|
1567
|
+
// Hook Lifecycle Notification Methods
|
|
1568
|
+
// ============================================================================
|
|
1569
|
+
/**
|
|
1570
|
+
* Emit hook pre-tool notification
|
|
1571
|
+
* Called before a tool begins execution
|
|
1572
|
+
*/
|
|
1573
|
+
emitHookPreTool(toolId, toolName, args) {
|
|
1574
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_PRE_TOOL, {
|
|
1575
|
+
toolId,
|
|
1576
|
+
toolName,
|
|
1577
|
+
args,
|
|
1578
|
+
timestamp: createTimestamp()
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Emit hook post-tool notification
|
|
1583
|
+
* Called after a tool completes execution
|
|
1584
|
+
*/
|
|
1585
|
+
emitHookPostTool(toolId, toolName, success, duration, output) {
|
|
1586
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_POST_TOOL, {
|
|
1587
|
+
toolId,
|
|
1588
|
+
toolName,
|
|
1589
|
+
success,
|
|
1590
|
+
duration,
|
|
1591
|
+
output,
|
|
1592
|
+
timestamp: createTimestamp()
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Emit hook file-modified notification
|
|
1597
|
+
* Called when a file is created, modified, or deleted
|
|
1598
|
+
*/
|
|
1599
|
+
emitHookFileModified(filePath, changeType, toolId) {
|
|
1600
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_FILE_MODIFIED, {
|
|
1601
|
+
filePath,
|
|
1602
|
+
changeType,
|
|
1603
|
+
toolId,
|
|
1604
|
+
timestamp: createTimestamp()
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Emit hook pre-prompt notification
|
|
1609
|
+
* Called before sending a prompt to the LLM
|
|
1610
|
+
*/
|
|
1611
|
+
emitHookPrePrompt(instruction, mentionedFiles) {
|
|
1612
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_PRE_PROMPT, {
|
|
1613
|
+
instruction,
|
|
1614
|
+
mentionedFiles,
|
|
1615
|
+
timestamp: createTimestamp()
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* Emit hook post-response notification
|
|
1620
|
+
* Called after receiving a response from the LLM
|
|
1621
|
+
*/
|
|
1622
|
+
emitHookPostResponse(tokensUsed, toolCallsCount, duration, tokensUsageStatus = "actual") {
|
|
1623
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_POST_RESPONSE, {
|
|
1624
|
+
tokensUsed,
|
|
1625
|
+
tokensUsageStatus,
|
|
1626
|
+
toolCallsCount,
|
|
1627
|
+
duration,
|
|
1628
|
+
timestamp: createTimestamp()
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Emit hook session-error notification
|
|
1633
|
+
* Called when an error occurs during agent execution
|
|
1634
|
+
*/
|
|
1635
|
+
emitHookSessionError(error, code, context) {
|
|
1636
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_SESSION_ERROR, {
|
|
1637
|
+
error,
|
|
1638
|
+
code,
|
|
1639
|
+
context,
|
|
1640
|
+
timestamp: createTimestamp()
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Emit hook stop notification
|
|
1645
|
+
* Called when agent finishes responding to a turn
|
|
1646
|
+
*/
|
|
1647
|
+
emitHookStop(tokensUsed, toolCallsCount, duration, tokensUsageStatus = "actual") {
|
|
1648
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_STOP, {
|
|
1649
|
+
tokensUsed,
|
|
1650
|
+
tokensUsageStatus,
|
|
1651
|
+
toolCallsCount,
|
|
1652
|
+
duration,
|
|
1653
|
+
timestamp: createTimestamp()
|
|
1654
|
+
});
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* Emit hook session-start notification
|
|
1658
|
+
* Called when a session begins
|
|
1659
|
+
*/
|
|
1660
|
+
emitHookSessionStart(sessionType) {
|
|
1661
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_SESSION_START, {
|
|
1662
|
+
sessionType,
|
|
1663
|
+
timestamp: createTimestamp()
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Emit hook session-end notification
|
|
1668
|
+
* Called when a session ends
|
|
1669
|
+
*/
|
|
1670
|
+
emitHookSessionEnd(reason, duration) {
|
|
1671
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_SESSION_END, {
|
|
1672
|
+
reason,
|
|
1673
|
+
duration,
|
|
1674
|
+
timestamp: createTimestamp()
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
/**
|
|
1678
|
+
* Emit hook subagent-stop notification
|
|
1679
|
+
* Called when a subagent finishes execution
|
|
1680
|
+
*/
|
|
1681
|
+
emitHookSubagentStop(subagentId, subagentName, subagentType, success, duration, error) {
|
|
1682
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_SUBAGENT_STOP, {
|
|
1683
|
+
subagentId,
|
|
1684
|
+
subagentName,
|
|
1685
|
+
subagentType,
|
|
1686
|
+
success,
|
|
1687
|
+
duration,
|
|
1688
|
+
error,
|
|
1689
|
+
timestamp: createTimestamp()
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Emit hook permission-request notification
|
|
1694
|
+
* Called when a permission dialog is about to be shown
|
|
1695
|
+
*/
|
|
1696
|
+
emitHookPermissionRequest(tool, path2, command, args) {
|
|
1697
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_PERMISSION_REQUEST, {
|
|
1698
|
+
tool,
|
|
1699
|
+
path: path2,
|
|
1700
|
+
command,
|
|
1701
|
+
args,
|
|
1702
|
+
timestamp: createTimestamp()
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
* Emit hook notification
|
|
1707
|
+
* Called when a notification is sent to the user
|
|
1708
|
+
*/
|
|
1709
|
+
emitHookNotification(notificationType, message) {
|
|
1710
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_NOTIFICATION, {
|
|
1711
|
+
notificationType,
|
|
1712
|
+
message,
|
|
1713
|
+
timestamp: createTimestamp()
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Handle changes decision from client (accept/reject)
|
|
1718
|
+
*/
|
|
1719
|
+
async handleChangesDecision(requestId, params) {
|
|
1720
|
+
const fileManager = this.agent?.getFileManager?.();
|
|
1721
|
+
if (!fileManager) {
|
|
1722
|
+
return {
|
|
1723
|
+
success: false,
|
|
1724
|
+
appliedCount: 0,
|
|
1725
|
+
skippedCount: 0,
|
|
1726
|
+
errors: [{ changeId: "unknown", error: "FileActionManager not available" }]
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
const { action, selectedChangeIds, batchId } = params;
|
|
1730
|
+
if (fileManager.getBatchId() !== batchId) {
|
|
1731
|
+
return {
|
|
1732
|
+
success: false,
|
|
1733
|
+
appliedCount: 0,
|
|
1734
|
+
skippedCount: 0,
|
|
1735
|
+
errors: [{ changeId: "unknown", error: `Batch ${batchId} not found or expired` }]
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
const pendingChanges = fileManager.getPendingChanges();
|
|
1739
|
+
const totalCount = pendingChanges.length;
|
|
1740
|
+
if (action === "reject_all") {
|
|
1741
|
+
fileManager.clearPendingChanges();
|
|
1742
|
+
fileManager.exitPreviewMode();
|
|
1743
|
+
return {
|
|
1744
|
+
success: true,
|
|
1745
|
+
appliedCount: 0,
|
|
1746
|
+
skippedCount: totalCount
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
const changeIds = action === "accept_selected" ? selectedChangeIds : void 0;
|
|
1750
|
+
const result = await fileManager.applyPendingChanges(changeIds);
|
|
1751
|
+
fileManager.exitPreviewMode();
|
|
1752
|
+
return {
|
|
1753
|
+
success: result.errors.length === 0,
|
|
1754
|
+
appliedCount: result.applied.length,
|
|
1755
|
+
skippedCount: totalCount - result.applied.length,
|
|
1756
|
+
errors: result.errors.length > 0 ? result.errors.map((e) => ({ changeId: e.id, error: e.error })) : void 0
|
|
1757
|
+
};
|
|
1758
|
+
}
|
|
1759
|
+
// ============================================================================
|
|
1760
|
+
// Skills Management Methods (Non-Interactive for RPC Mode)
|
|
1761
|
+
// ============================================================================
|
|
1762
|
+
/**
|
|
1763
|
+
* Get community skills registry
|
|
1764
|
+
*/
|
|
1765
|
+
async handleGetSkillsRegistry(requestId, params) {
|
|
1766
|
+
try {
|
|
1767
|
+
const { CommunitySkillsCache } = await import("./CommunitySkillsCache-ZACDPD4J.js");
|
|
1768
|
+
const { GitHubRegistryFetcher } = await import("./GitHubRegistryFetcher-J2BWPXJF.js");
|
|
1769
|
+
const cache = new CommunitySkillsCache();
|
|
1770
|
+
const fetcher = new GitHubRegistryFetcher();
|
|
1771
|
+
let registry;
|
|
1772
|
+
if (params?.forceRefresh) {
|
|
1773
|
+
process.stderr.write("[RPC] Force refreshing skills registry from GitHub\n");
|
|
1774
|
+
registry = await fetcher.fetchRegistry();
|
|
1775
|
+
await cache.setRegistry(registry);
|
|
1776
|
+
} else {
|
|
1777
|
+
const cached = await cache.getRegistry();
|
|
1778
|
+
if (cached) {
|
|
1779
|
+
registry = cached;
|
|
1780
|
+
} else {
|
|
1781
|
+
process.stderr.write("[RPC] Fetching skills registry from GitHub\n");
|
|
1782
|
+
registry = await fetcher.fetchRegistry();
|
|
1783
|
+
await cache.setRegistry(registry);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
const skills = registry.skills.map((skill) => ({
|
|
1787
|
+
id: skill.id,
|
|
1788
|
+
name: skill.name,
|
|
1789
|
+
description: skill.description,
|
|
1790
|
+
category: skill.category,
|
|
1791
|
+
tags: skill.tags,
|
|
1792
|
+
rating: skill.rating,
|
|
1793
|
+
downloadCount: skill.downloadCount,
|
|
1794
|
+
isFeatured: skill.isFeatured,
|
|
1795
|
+
isCurated: skill.isCurated
|
|
1796
|
+
}));
|
|
1797
|
+
return {
|
|
1798
|
+
success: true,
|
|
1799
|
+
skills,
|
|
1800
|
+
categories: registry.categories
|
|
1801
|
+
};
|
|
1802
|
+
} catch (error) {
|
|
1803
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1804
|
+
process.stderr.write(`[RPC] Failed to get skills registry: ${message}
|
|
1805
|
+
`);
|
|
1806
|
+
return {
|
|
1807
|
+
success: false,
|
|
1808
|
+
skills: [],
|
|
1809
|
+
categories: [],
|
|
1810
|
+
error: message
|
|
1811
|
+
};
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Install a skill by name (non-interactive)
|
|
1816
|
+
*/
|
|
1817
|
+
async handleInstallSkill(requestId, params) {
|
|
1818
|
+
try {
|
|
1819
|
+
const skillsRegistry = this.agent?.getSkillsRegistry?.();
|
|
1820
|
+
if (!skillsRegistry) {
|
|
1821
|
+
return {
|
|
1822
|
+
success: false,
|
|
1823
|
+
error: "Skills registry not available"
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
const workspaceRoot = this.workspace;
|
|
1827
|
+
const { CommunitySkillsCache } = await import("./CommunitySkillsCache-ZACDPD4J.js");
|
|
1828
|
+
const { GitHubRegistryFetcher } = await import("./GitHubRegistryFetcher-J2BWPXJF.js");
|
|
1829
|
+
const { AUTOHAND_PATHS, PROJECT_DIR_NAME } = await import("./constants-EJFAWJQI.js");
|
|
1830
|
+
const path2 = await import("path");
|
|
1831
|
+
const cache = new CommunitySkillsCache();
|
|
1832
|
+
const fetcher = new GitHubRegistryFetcher();
|
|
1833
|
+
let registry = await cache.getRegistry();
|
|
1834
|
+
if (!registry) {
|
|
1835
|
+
process.stderr.write("[RPC] Fetching skills registry for install\n");
|
|
1836
|
+
registry = await fetcher.fetchRegistry();
|
|
1837
|
+
await cache.setRegistry(registry);
|
|
1838
|
+
}
|
|
1839
|
+
const skill = fetcher.findSkill(registry.skills, params.skillName);
|
|
1840
|
+
if (!skill) {
|
|
1841
|
+
const similar = fetcher.findSimilarSkills(registry.skills, params.skillName, 3);
|
|
1842
|
+
const suggestions = similar.map((s) => s.name).join(", ");
|
|
1843
|
+
return {
|
|
1844
|
+
success: false,
|
|
1845
|
+
error: `Skill not found: ${params.skillName}${suggestions ? `. Did you mean: ${suggestions}?` : ""}`
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
const targetDir = params.scope === "project" ? path2.join(workspaceRoot, PROJECT_DIR_NAME, "skills") : AUTOHAND_PATHS.skills;
|
|
1849
|
+
const isInstalled = await skillsRegistry.isSkillInstalled(skill.name, targetDir);
|
|
1850
|
+
if (isInstalled && !params.force) {
|
|
1851
|
+
return {
|
|
1852
|
+
success: false,
|
|
1853
|
+
error: `Skill "${skill.name}" already exists. Use force=true to overwrite.`
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
process.stderr.write(`[RPC] Installing skill ${skill.name} to ${params.scope}
|
|
1857
|
+
`);
|
|
1858
|
+
let files = await cache.getSkillDirectory(skill.id);
|
|
1859
|
+
if (!files) {
|
|
1860
|
+
process.stderr.write(`[RPC] Fetching skill files from GitHub
|
|
1861
|
+
`);
|
|
1862
|
+
files = await fetcher.fetchSkillDirectory(skill);
|
|
1863
|
+
await cache.setSkillDirectory(skill.id, files);
|
|
1864
|
+
}
|
|
1865
|
+
const result = await skillsRegistry.importCommunitySkillDirectory(
|
|
1866
|
+
skill.name,
|
|
1867
|
+
files,
|
|
1868
|
+
targetDir,
|
|
1869
|
+
isInstalled
|
|
1870
|
+
// force if overwriting
|
|
1871
|
+
);
|
|
1872
|
+
if (result.success) {
|
|
1873
|
+
process.stderr.write(`[RPC] Successfully installed ${skill.name}
|
|
1874
|
+
`);
|
|
1875
|
+
return {
|
|
1876
|
+
success: true,
|
|
1877
|
+
skillName: skill.name,
|
|
1878
|
+
path: result.path
|
|
1879
|
+
};
|
|
1880
|
+
} else {
|
|
1881
|
+
return {
|
|
1882
|
+
success: false,
|
|
1883
|
+
error: result.error || "Installation failed"
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1886
|
+
} catch (error) {
|
|
1887
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1888
|
+
process.stderr.write(`[RPC] Failed to install skill: ${message}
|
|
1889
|
+
`);
|
|
1890
|
+
return {
|
|
1891
|
+
success: false,
|
|
1892
|
+
error: message
|
|
1893
|
+
};
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
// ============================================================================
|
|
1897
|
+
// Learn Command Methods (RPC Mode)
|
|
1898
|
+
// ============================================================================
|
|
1899
|
+
/**
|
|
1900
|
+
* Handle /learn recommend - analyze project and recommend skills
|
|
1901
|
+
*/
|
|
1902
|
+
async handleLearnRecommend(requestId, params) {
|
|
1903
|
+
try {
|
|
1904
|
+
const { ProjectAnalyzer } = await import("./autoSkill-66PKCYTW.js");
|
|
1905
|
+
const { CommunitySkillsCache } = await import("./CommunitySkillsCache-ZACDPD4J.js");
|
|
1906
|
+
const { GitHubRegistryFetcher } = await import("./GitHubRegistryFetcher-J2BWPXJF.js");
|
|
1907
|
+
const { fetchRegistryWithFallback } = await import("./communityInstaller-RVL4STPS.js");
|
|
1908
|
+
const { LearnAdvisor } = await import("./LearnAdvisor-KKEQ5QCV.js");
|
|
1909
|
+
const workspace = this.workspace || process.cwd();
|
|
1910
|
+
const deep = params?.deep ?? false;
|
|
1911
|
+
writeNotification(RPC_NOTIFICATIONS.LEARN_PROGRESS, {
|
|
1912
|
+
status: "analyzing",
|
|
1913
|
+
timestamp: createTimestamp()
|
|
1914
|
+
});
|
|
1915
|
+
process.stderr.write(`[RPC] Learn recommend: analyzing project (deep=${deep})
|
|
1916
|
+
`);
|
|
1917
|
+
const analyzer = new ProjectAnalyzer(workspace);
|
|
1918
|
+
const analysis = await analyzer.analyze();
|
|
1919
|
+
writeNotification(RPC_NOTIFICATIONS.LEARN_PROGRESS, {
|
|
1920
|
+
status: "loading-registry",
|
|
1921
|
+
timestamp: createTimestamp()
|
|
1922
|
+
});
|
|
1923
|
+
const cache = new CommunitySkillsCache();
|
|
1924
|
+
const fetcher = new GitHubRegistryFetcher();
|
|
1925
|
+
let registry;
|
|
1926
|
+
try {
|
|
1927
|
+
registry = await fetchRegistryWithFallback(cache, fetcher);
|
|
1928
|
+
} catch {
|
|
1929
|
+
}
|
|
1930
|
+
const skillsRegistry = this.agent?.getSkillsRegistry?.();
|
|
1931
|
+
const installedSkills = skillsRegistry?.listSkills() ?? [];
|
|
1932
|
+
const registrySkills = registry?.skills ?? [];
|
|
1933
|
+
writeNotification(RPC_NOTIFICATIONS.LEARN_PROGRESS, {
|
|
1934
|
+
status: "evaluating",
|
|
1935
|
+
timestamp: createTimestamp()
|
|
1936
|
+
});
|
|
1937
|
+
const llm = this.agent?.getLlmProvider?.();
|
|
1938
|
+
if (!llm) {
|
|
1939
|
+
return {
|
|
1940
|
+
success: false,
|
|
1941
|
+
projectSummary: "",
|
|
1942
|
+
audit: [],
|
|
1943
|
+
recommendations: [],
|
|
1944
|
+
gapAnalysis: null,
|
|
1945
|
+
error: "LLM provider not available"
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
const advisor = new LearnAdvisor(llm);
|
|
1949
|
+
const result = await advisor.analyze(analysis, installedSkills, registrySkills);
|
|
1950
|
+
return {
|
|
1951
|
+
success: true,
|
|
1952
|
+
projectSummary: result.projectSummary,
|
|
1953
|
+
audit: result.audit,
|
|
1954
|
+
recommendations: result.recommendations,
|
|
1955
|
+
gapAnalysis: result.gapAnalysis
|
|
1956
|
+
};
|
|
1957
|
+
} catch (error) {
|
|
1958
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1959
|
+
process.stderr.write(`[RPC] Learn recommend failed: ${message}
|
|
1960
|
+
`);
|
|
1961
|
+
return {
|
|
1962
|
+
success: false,
|
|
1963
|
+
projectSummary: "",
|
|
1964
|
+
audit: [],
|
|
1965
|
+
recommendations: [],
|
|
1966
|
+
gapAnalysis: null,
|
|
1967
|
+
error: message
|
|
1968
|
+
};
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
/**
|
|
1972
|
+
* Handle /learn update - regenerate stale LLM-generated skills
|
|
1973
|
+
*/
|
|
1974
|
+
async handleLearnUpdate(_requestId, _params) {
|
|
1975
|
+
try {
|
|
1976
|
+
const { ProjectAnalyzer } = await import("./autoSkill-66PKCYTW.js");
|
|
1977
|
+
const { computeProjectHash, injectGeneratedMetadata } = await import("./communityInstaller-RVL4STPS.js");
|
|
1978
|
+
const { LearnAdvisor } = await import("./LearnAdvisor-KKEQ5QCV.js");
|
|
1979
|
+
const fse = await import("fs-extra");
|
|
1980
|
+
const workspace = this.workspace || process.cwd();
|
|
1981
|
+
writeNotification(RPC_NOTIFICATIONS.LEARN_PROGRESS, {
|
|
1982
|
+
status: "updating",
|
|
1983
|
+
timestamp: createTimestamp()
|
|
1984
|
+
});
|
|
1985
|
+
process.stderr.write("[RPC] Learn update: checking for stale skills\n");
|
|
1986
|
+
const analyzer = new ProjectAnalyzer(workspace);
|
|
1987
|
+
const analysis = await analyzer.analyze();
|
|
1988
|
+
const currentHash = computeProjectHash(analysis);
|
|
1989
|
+
const skillsRegistry = this.agent?.getSkillsRegistry?.();
|
|
1990
|
+
if (!skillsRegistry) {
|
|
1991
|
+
return { success: false, updated: 0, unchanged: 0, results: [], error: "Skills registry not available" };
|
|
1992
|
+
}
|
|
1993
|
+
const allSkills = skillsRegistry.listSkills();
|
|
1994
|
+
const generatedSkills = allSkills.filter(
|
|
1995
|
+
(s) => s.metadata?.["agentskill-source"] === "llm-generated"
|
|
1996
|
+
);
|
|
1997
|
+
if (generatedSkills.length === 0) {
|
|
1998
|
+
return { success: true, updated: 0, unchanged: 0, results: [] };
|
|
1999
|
+
}
|
|
2000
|
+
const llm = this.agent?.getLlmProvider?.();
|
|
2001
|
+
if (!llm) {
|
|
2002
|
+
return { success: false, updated: 0, unchanged: 0, results: [], error: "LLM provider not available" };
|
|
2003
|
+
}
|
|
2004
|
+
const advisor = new LearnAdvisor(llm);
|
|
2005
|
+
let updated = 0;
|
|
2006
|
+
let unchanged = 0;
|
|
2007
|
+
const results = [];
|
|
2008
|
+
for (const skill of generatedSkills) {
|
|
2009
|
+
const storedHash = skill.metadata?.["agentskill-project-hash"];
|
|
2010
|
+
if (storedHash === currentHash) {
|
|
2011
|
+
unchanged++;
|
|
2012
|
+
results.push({ name: skill.name, status: "unchanged" });
|
|
2013
|
+
continue;
|
|
2014
|
+
}
|
|
2015
|
+
const generated = await advisor.generateSkill(analysis, null, []);
|
|
2016
|
+
if (!generated) {
|
|
2017
|
+
results.push({ name: skill.name, status: "failed" });
|
|
2018
|
+
continue;
|
|
2019
|
+
}
|
|
2020
|
+
let frontmatter = `---
|
|
2021
|
+
name: ${generated.name}
|
|
2022
|
+
description: ${generated.description}
|
|
2023
|
+
`;
|
|
2024
|
+
if (generated.allowedTools.length > 0) {
|
|
2025
|
+
frontmatter += `allowed-tools: ${generated.allowedTools.join(" ")}
|
|
2026
|
+
`;
|
|
2027
|
+
}
|
|
2028
|
+
frontmatter += `---
|
|
2029
|
+
|
|
2030
|
+
`;
|
|
2031
|
+
let content = frontmatter + generated.body + "\n";
|
|
2032
|
+
content = injectGeneratedMetadata(content, skill.name, currentHash);
|
|
2033
|
+
try {
|
|
2034
|
+
await fse.writeFile(skill.path, content, "utf-8");
|
|
2035
|
+
updated++;
|
|
2036
|
+
results.push({ name: skill.name, status: "updated" });
|
|
2037
|
+
} catch {
|
|
2038
|
+
results.push({ name: skill.name, status: "failed" });
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
return { success: true, updated, unchanged, results };
|
|
2042
|
+
} catch (error) {
|
|
2043
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
2044
|
+
process.stderr.write(`[RPC] Learn update failed: ${message}
|
|
2045
|
+
`);
|
|
2046
|
+
return { success: false, updated: 0, unchanged: 0, results: [], error: message };
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Handle /learn generate - generate a custom skill for the project
|
|
2051
|
+
*/
|
|
2052
|
+
async handleLearnGenerate(requestId, params) {
|
|
2053
|
+
try {
|
|
2054
|
+
const { ProjectAnalyzer } = await import("./autoSkill-66PKCYTW.js");
|
|
2055
|
+
const { computeProjectHash, injectGeneratedMetadata } = await import("./communityInstaller-RVL4STPS.js");
|
|
2056
|
+
const { LearnAdvisor } = await import("./LearnAdvisor-KKEQ5QCV.js");
|
|
2057
|
+
const { AUTOHAND_PATHS, PROJECT_DIR_NAME } = await import("./constants-EJFAWJQI.js");
|
|
2058
|
+
const fse = await import("fs-extra");
|
|
2059
|
+
const path2 = await import("path");
|
|
2060
|
+
const workspace = this.workspace || process.cwd();
|
|
2061
|
+
const scope = params.scope;
|
|
2062
|
+
writeNotification(RPC_NOTIFICATIONS.LEARN_PROGRESS, {
|
|
2063
|
+
status: "generating",
|
|
2064
|
+
timestamp: createTimestamp()
|
|
2065
|
+
});
|
|
2066
|
+
process.stderr.write(`[RPC] Learn generate: scope=${scope}
|
|
2067
|
+
`);
|
|
2068
|
+
const llm = this.agent?.getLlmProvider?.();
|
|
2069
|
+
if (!llm) {
|
|
2070
|
+
return { success: false, error: "LLM provider not available" };
|
|
2071
|
+
}
|
|
2072
|
+
const analyzer = new ProjectAnalyzer(workspace);
|
|
2073
|
+
const analysis = await analyzer.analyze();
|
|
2074
|
+
const projectHash = computeProjectHash(analysis);
|
|
2075
|
+
const advisor = new LearnAdvisor(llm);
|
|
2076
|
+
const generated = await advisor.generateSkill(analysis, null, []);
|
|
2077
|
+
if (!generated) {
|
|
2078
|
+
return { success: false, error: "Failed to generate a custom skill" };
|
|
2079
|
+
}
|
|
2080
|
+
let frontmatter = `---
|
|
2081
|
+
name: ${generated.name}
|
|
2082
|
+
description: ${generated.description}
|
|
2083
|
+
`;
|
|
2084
|
+
if (generated.allowedTools.length > 0) {
|
|
2085
|
+
frontmatter += `allowed-tools: ${generated.allowedTools.join(" ")}
|
|
2086
|
+
`;
|
|
2087
|
+
}
|
|
2088
|
+
frontmatter += `---
|
|
2089
|
+
|
|
2090
|
+
`;
|
|
2091
|
+
let skillContent = frontmatter + generated.body + "\n";
|
|
2092
|
+
skillContent = injectGeneratedMetadata(skillContent, generated.name, projectHash);
|
|
2093
|
+
const targetDir = scope === "project" ? path2.join(workspace, PROJECT_DIR_NAME, "skills") : AUTOHAND_PATHS.skills;
|
|
2094
|
+
const skillDir = path2.join(targetDir, generated.name);
|
|
2095
|
+
await fse.ensureDir(skillDir);
|
|
2096
|
+
const skillPath = path2.join(skillDir, "SKILL.md");
|
|
2097
|
+
await fse.writeFile(skillPath, skillContent, "utf-8");
|
|
2098
|
+
return { success: true, skillName: generated.name, skillPath };
|
|
2099
|
+
} catch (error) {
|
|
2100
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
2101
|
+
process.stderr.write(`[RPC] Learn generate failed: ${message}
|
|
2102
|
+
`);
|
|
2103
|
+
return { success: false, error: message };
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
// ============================================================================
|
|
2107
|
+
// Session History, YOLO, and MCP Handlers
|
|
2108
|
+
// ============================================================================
|
|
2109
|
+
/**
|
|
2110
|
+
* Get paginated session history
|
|
2111
|
+
*/
|
|
2112
|
+
async handleGetHistory(_requestId, params) {
|
|
2113
|
+
const sessionManager = this.agent?.getSessionManager?.();
|
|
2114
|
+
if (!sessionManager) {
|
|
2115
|
+
return { sessions: [], currentPage: 1, totalPages: 0, totalItems: 0 };
|
|
2116
|
+
}
|
|
2117
|
+
try {
|
|
2118
|
+
const allSessions = await sessionManager.listSessions();
|
|
2119
|
+
const page = params?.page ?? 1;
|
|
2120
|
+
const pageSize = params?.pageSize ?? 20;
|
|
2121
|
+
const totalItems = allSessions.length;
|
|
2122
|
+
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
|
|
2123
|
+
const startIndex = (page - 1) * pageSize;
|
|
2124
|
+
const pageSessions = allSessions.slice(startIndex, startIndex + pageSize);
|
|
2125
|
+
return {
|
|
2126
|
+
sessions: pageSessions.map((s) => ({
|
|
2127
|
+
sessionId: s.sessionId,
|
|
2128
|
+
createdAt: s.createdAt,
|
|
2129
|
+
lastActiveAt: s.lastActiveAt ?? s.createdAt,
|
|
2130
|
+
projectName: s.projectName ?? "",
|
|
2131
|
+
model: s.model ?? "",
|
|
2132
|
+
messageCount: s.messageCount ?? 0,
|
|
2133
|
+
status: s.status ?? "completed"
|
|
2134
|
+
})),
|
|
2135
|
+
currentPage: page,
|
|
2136
|
+
totalPages,
|
|
2137
|
+
totalItems
|
|
2138
|
+
};
|
|
2139
|
+
} catch (error) {
|
|
2140
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2141
|
+
process.stderr.write(`[RPC] Failed to get history: ${message}
|
|
2142
|
+
`);
|
|
2143
|
+
return { sessions: [], currentPage: 1, totalPages: 0, totalItems: 0 };
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Get a specific session's metadata and messages
|
|
2148
|
+
*/
|
|
2149
|
+
async handleGetSession(_requestId, params) {
|
|
2150
|
+
const sessionManager = this.agent?.getSessionManager?.();
|
|
2151
|
+
if (!sessionManager) {
|
|
2152
|
+
return { success: false, error: "Session manager not available" };
|
|
2153
|
+
}
|
|
2154
|
+
try {
|
|
2155
|
+
const session = await sessionManager.loadSession(params.sessionId);
|
|
2156
|
+
const m = session.metadata;
|
|
2157
|
+
const messages = session.getMessages().map((msg) => ({
|
|
2158
|
+
id: msg.role === "user" ? `user-${crypto.randomUUID()}` : `msg-${crypto.randomUUID()}`,
|
|
2159
|
+
role: msg.role,
|
|
2160
|
+
content: msg.content,
|
|
2161
|
+
timestamp: new Date(m.createdAt).toISOString(),
|
|
2162
|
+
toolCalls: (msg.toolCalls ?? []).map((tc) => ({
|
|
2163
|
+
id: tc.callId ?? "",
|
|
2164
|
+
name: tc.name ?? "",
|
|
2165
|
+
args: tc.arguments ?? {}
|
|
2166
|
+
}))
|
|
2167
|
+
}));
|
|
2168
|
+
return {
|
|
2169
|
+
success: true,
|
|
2170
|
+
sessionId: m.sessionId,
|
|
2171
|
+
projectName: m.projectName ?? "",
|
|
2172
|
+
model: m.model ?? "",
|
|
2173
|
+
messageCount: m.messageCount ?? 0,
|
|
2174
|
+
status: m.status ?? "completed",
|
|
2175
|
+
createdAt: m.createdAt,
|
|
2176
|
+
lastActiveAt: m.lastActiveAt ?? m.createdAt,
|
|
2177
|
+
summary: m.summary,
|
|
2178
|
+
messages,
|
|
2179
|
+
workspaceRoot: m.projectPath ?? ""
|
|
2180
|
+
};
|
|
2181
|
+
} catch (error) {
|
|
2182
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2183
|
+
process.stderr.write(`[RPC] Failed to get session: ${message}
|
|
2184
|
+
`);
|
|
2185
|
+
return {
|
|
2186
|
+
success: false,
|
|
2187
|
+
error: message,
|
|
2188
|
+
sessionId: params.sessionId,
|
|
2189
|
+
projectName: "",
|
|
2190
|
+
model: "",
|
|
2191
|
+
messageCount: 0,
|
|
2192
|
+
status: "completed",
|
|
2193
|
+
createdAt: "",
|
|
2194
|
+
lastActiveAt: "",
|
|
2195
|
+
messages: [],
|
|
2196
|
+
workspaceRoot: ""
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* Set YOLO (unrestricted) mode with pattern and optional timeout
|
|
2202
|
+
*/
|
|
2203
|
+
handleYoloSet(_requestId, params) {
|
|
2204
|
+
const permissionManager = this.agent?.getPermissionManager?.();
|
|
2205
|
+
if (!permissionManager) {
|
|
2206
|
+
return { success: false };
|
|
2207
|
+
}
|
|
2208
|
+
try {
|
|
2209
|
+
const revertGeneration = ++this.yoloRevertGeneration;
|
|
2210
|
+
if (this.yoloRevertTimer) {
|
|
2211
|
+
clearTimeout(this.yoloRevertTimer);
|
|
2212
|
+
this.yoloRevertTimer = null;
|
|
2213
|
+
}
|
|
2214
|
+
permissionManager.setMode("unrestricted");
|
|
2215
|
+
process.stderr.write(`[RPC] YOLO mode enabled with pattern: ${params.pattern}
|
|
2216
|
+
`);
|
|
2217
|
+
let expiresIn;
|
|
2218
|
+
if (params.timeoutSeconds && params.timeoutSeconds > 0) {
|
|
2219
|
+
expiresIn = params.timeoutSeconds;
|
|
2220
|
+
this.yoloRevertTimer = setTimeout(() => {
|
|
2221
|
+
if (this.yoloRevertGeneration !== revertGeneration) {
|
|
2222
|
+
return;
|
|
2223
|
+
}
|
|
2224
|
+
this.yoloRevertTimer = null;
|
|
2225
|
+
permissionManager.setMode("interactive");
|
|
2226
|
+
process.stderr.write(`[RPC] YOLO mode expired, reverted to interactive
|
|
2227
|
+
`);
|
|
2228
|
+
}, params.timeoutSeconds * 1e3);
|
|
2229
|
+
this.yoloRevertTimer.unref?.();
|
|
2230
|
+
}
|
|
2231
|
+
return { success: true, expiresIn };
|
|
2232
|
+
} catch (error) {
|
|
2233
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2234
|
+
process.stderr.write(`[RPC] Failed to set YOLO mode: ${message}
|
|
2235
|
+
`);
|
|
2236
|
+
return { success: false };
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
/**
|
|
2240
|
+
* List all MCP servers and their connection status
|
|
2241
|
+
*/
|
|
2242
|
+
handleMcpListServers(_requestId) {
|
|
2243
|
+
const mcpManager = this.agent?.getMcpManager?.();
|
|
2244
|
+
if (!mcpManager) {
|
|
2245
|
+
return { servers: [] };
|
|
2246
|
+
}
|
|
2247
|
+
return { servers: mcpManager.getServers() };
|
|
2248
|
+
}
|
|
2249
|
+
/**
|
|
2250
|
+
* List all MCP tools, optionally filtered by server name
|
|
2251
|
+
*/
|
|
2252
|
+
handleMcpListTools(_requestId, params) {
|
|
2253
|
+
const mcpManager = this.agent?.getMcpManager?.();
|
|
2254
|
+
if (!mcpManager) {
|
|
2255
|
+
return { tools: [] };
|
|
2256
|
+
}
|
|
2257
|
+
const allTools = params?.serverName ? mcpManager.getToolsForServer(params.serverName) : mcpManager.getAllTools();
|
|
2258
|
+
return {
|
|
2259
|
+
tools: allTools.map((t) => {
|
|
2260
|
+
const parsed = McpClientManager.parseMcpToolName(t.name);
|
|
2261
|
+
return {
|
|
2262
|
+
name: t.name,
|
|
2263
|
+
description: t.description,
|
|
2264
|
+
serverName: parsed?.serverName ?? "unknown"
|
|
2265
|
+
};
|
|
2266
|
+
})
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* List persisted meta-tools and registry diagnostics for non-interactive clients.
|
|
2271
|
+
*/
|
|
2272
|
+
handleGetToolsRegistry() {
|
|
2273
|
+
const registry = this.agent?.getToolsRegistry?.();
|
|
2274
|
+
if (!registry) {
|
|
2275
|
+
return { tools: [], diagnostics: [] };
|
|
2276
|
+
}
|
|
2277
|
+
return {
|
|
2278
|
+
tools: registry.listMetaTools({ includeDisabled: true }).map((tool) => ({
|
|
2279
|
+
name: tool.name,
|
|
2280
|
+
description: tool.description,
|
|
2281
|
+
source: "meta",
|
|
2282
|
+
scope: tool.scope,
|
|
2283
|
+
disabled: tool.disabled,
|
|
2284
|
+
createdAt: tool.createdAt,
|
|
2285
|
+
schemaVersion: tool.schemaVersion,
|
|
2286
|
+
handlerPreview: tool.handler.length > 140 ? `${tool.handler.slice(0, 137)}...` : tool.handler,
|
|
2287
|
+
reuseHint: `Use ${tool.name} instead of creating another tool for: ${tool.description}`
|
|
2288
|
+
})),
|
|
2289
|
+
diagnostics: registry.getDiagnostics()
|
|
2290
|
+
};
|
|
2291
|
+
}
|
|
2292
|
+
// ============================================================================
|
|
2293
|
+
// MCP Bridge Methods (VS Code <-> CLI bidirectional tool bridging)
|
|
2294
|
+
// ============================================================================
|
|
2295
|
+
/**
|
|
2296
|
+
* Receive VS Code MCP tool descriptors from the extension.
|
|
2297
|
+
* These tools become available for the agent to invoke via the extension.
|
|
2298
|
+
* Tool names are stored with a 'vscode__' prefix to distinguish them.
|
|
2299
|
+
*/
|
|
2300
|
+
handleMcpSetVscodeTools(_requestId, params) {
|
|
2301
|
+
this.vscodeTools.clear();
|
|
2302
|
+
for (const tool of params.tools) {
|
|
2303
|
+
const prefixedName = `vscode__${tool.serverName}__${tool.name}`;
|
|
2304
|
+
this.vscodeTools.set(prefixedName, {
|
|
2305
|
+
name: tool.name,
|
|
2306
|
+
description: tool.description,
|
|
2307
|
+
serverName: tool.serverName,
|
|
2308
|
+
inputSchema: tool.inputSchema
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2311
|
+
process.stderr.write(
|
|
2312
|
+
`[RPC] MCP bridge: registered ${this.vscodeTools.size} VS Code tools
|
|
2313
|
+
`
|
|
2314
|
+
);
|
|
2315
|
+
const allTools = this.getVscodeToolsList();
|
|
2316
|
+
writeNotification(RPC_NOTIFICATIONS.MCP_TOOLS_CHANGED, {
|
|
2317
|
+
tools: allTools,
|
|
2318
|
+
timestamp: createTimestamp()
|
|
2319
|
+
});
|
|
2320
|
+
return { success: true };
|
|
2321
|
+
}
|
|
2322
|
+
/**
|
|
2323
|
+
* Get the list of registered VS Code tools for notifications
|
|
2324
|
+
*/
|
|
2325
|
+
getVscodeToolsList() {
|
|
2326
|
+
const tools = [];
|
|
2327
|
+
for (const [prefixedName, tool] of this.vscodeTools) {
|
|
2328
|
+
tools.push({
|
|
2329
|
+
name: prefixedName,
|
|
2330
|
+
description: tool.description,
|
|
2331
|
+
serverName: tool.serverName
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
return tools;
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* Invoke a VS Code MCP tool by sending a notification to the extension
|
|
2338
|
+
* and waiting for the response. Called internally when the agent uses
|
|
2339
|
+
* a tool with the 'vscode__' prefix.
|
|
2340
|
+
*/
|
|
2341
|
+
async invokeVscodeTool(toolName, args) {
|
|
2342
|
+
const tool = this.vscodeTools.get(toolName);
|
|
2343
|
+
if (!tool) {
|
|
2344
|
+
throw new Error(`VS Code tool not found: ${toolName}`);
|
|
2345
|
+
}
|
|
2346
|
+
const requestId = generateId("mcp-invoke");
|
|
2347
|
+
writeNotification(RPC_NOTIFICATIONS.MCP_INVOKE_REQUEST, {
|
|
2348
|
+
requestId,
|
|
2349
|
+
toolName,
|
|
2350
|
+
args,
|
|
2351
|
+
timestamp: createTimestamp()
|
|
2352
|
+
});
|
|
2353
|
+
return new Promise((resolve, reject) => {
|
|
2354
|
+
const timeout = setTimeout(() => {
|
|
2355
|
+
this.pendingVscodeInvocations.delete(requestId);
|
|
2356
|
+
reject(new Error(`VS Code tool invocation timed out: ${toolName}`));
|
|
2357
|
+
}, 3e5);
|
|
2358
|
+
this.pendingVscodeInvocations.set(requestId, {
|
|
2359
|
+
resolve: (result) => {
|
|
2360
|
+
clearTimeout(timeout);
|
|
2361
|
+
resolve(result);
|
|
2362
|
+
},
|
|
2363
|
+
reject: (error) => {
|
|
2364
|
+
clearTimeout(timeout);
|
|
2365
|
+
reject(error);
|
|
2366
|
+
}
|
|
2367
|
+
});
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
/**
|
|
2371
|
+
* Handle the invoke response from the extension for a pending VS Code tool call.
|
|
2372
|
+
* Resolves or rejects the promise created in invokeVscodeTool.
|
|
2373
|
+
*/
|
|
2374
|
+
handleMcpInvokeResponse(_requestId, params) {
|
|
2375
|
+
const pending = this.pendingVscodeInvocations.get(params.requestId);
|
|
2376
|
+
if (!pending) {
|
|
2377
|
+
process.stderr.write(
|
|
2378
|
+
`[RPC] MCP bridge: invoke response for unknown request ${params.requestId}
|
|
2379
|
+
`
|
|
2380
|
+
);
|
|
2381
|
+
return { success: false };
|
|
2382
|
+
}
|
|
2383
|
+
this.pendingVscodeInvocations.delete(params.requestId);
|
|
2384
|
+
if (params.success) {
|
|
2385
|
+
pending.resolve(params.result ?? "");
|
|
2386
|
+
} else {
|
|
2387
|
+
pending.reject(new Error(params.error ?? "VS Code tool invocation failed"));
|
|
2388
|
+
}
|
|
2389
|
+
return { success: true };
|
|
2390
|
+
}
|
|
2391
|
+
/**
|
|
2392
|
+
* Return MCP server configurations from the CLI config.
|
|
2393
|
+
* Sensitive environment variables (keys, tokens, secrets) are sanitized.
|
|
2394
|
+
*/
|
|
2395
|
+
handleMcpGetServerConfigs(_requestId) {
|
|
2396
|
+
const configs = this.mcpServerConfigs.map((server) => ({
|
|
2397
|
+
name: server.name,
|
|
2398
|
+
transport: server.transport,
|
|
2399
|
+
command: server.command,
|
|
2400
|
+
args: server.args,
|
|
2401
|
+
url: server.url,
|
|
2402
|
+
env: server.env ? this.sanitizeEnv(server.env) : void 0,
|
|
2403
|
+
headers: server.headers ? this.sanitizeHeaders(server.headers) : void 0,
|
|
2404
|
+
autoConnect: server.autoConnect
|
|
2405
|
+
}));
|
|
2406
|
+
return { configs };
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Check if a tool name is a registered VS Code MCP tool
|
|
2410
|
+
*/
|
|
2411
|
+
isVscodeTool(toolName) {
|
|
2412
|
+
return this.vscodeTools.has(toolName);
|
|
2413
|
+
}
|
|
2414
|
+
/**
|
|
2415
|
+
* Sanitize environment variables by redacting values that look like secrets.
|
|
2416
|
+
* Keeps the key names but replaces sensitive values with '***'.
|
|
2417
|
+
*/
|
|
2418
|
+
sanitizeEnv(env) {
|
|
2419
|
+
const sensitivePatterns = /key|token|secret|password|credential|auth/i;
|
|
2420
|
+
const sanitized = {};
|
|
2421
|
+
for (const [key, value] of Object.entries(env)) {
|
|
2422
|
+
if (sensitivePatterns.test(key)) {
|
|
2423
|
+
sanitized[key] = "***";
|
|
2424
|
+
} else {
|
|
2425
|
+
sanitized[key] = value;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
return sanitized;
|
|
2429
|
+
}
|
|
2430
|
+
/**
|
|
2431
|
+
* Sanitize HTTP headers by redacting values that look like auth tokens.
|
|
2432
|
+
*/
|
|
2433
|
+
sanitizeHeaders(headers) {
|
|
2434
|
+
const sensitivePatterns = /authorization|token|key|secret|bearer/i;
|
|
2435
|
+
const sanitized = {};
|
|
2436
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
2437
|
+
if (sensitivePatterns.test(key)) {
|
|
2438
|
+
sanitized[key] = "***";
|
|
2439
|
+
} else {
|
|
2440
|
+
sanitized[key] = value;
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
return sanitized;
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Shutdown the adapter
|
|
2447
|
+
*/
|
|
2448
|
+
startKeepalive() {
|
|
2449
|
+
this.stopKeepalive();
|
|
2450
|
+
this.keepaliveInterval = setInterval(() => {
|
|
2451
|
+
writeNotification(RPC_NOTIFICATIONS.PING, {
|
|
2452
|
+
timestamp: createTimestamp(),
|
|
2453
|
+
status: this.status,
|
|
2454
|
+
turnId: this.currentTurnId
|
|
2455
|
+
});
|
|
2456
|
+
}, this.KEEPALIVE_MS);
|
|
2457
|
+
}
|
|
2458
|
+
stopKeepalive() {
|
|
2459
|
+
if (this.keepaliveInterval) {
|
|
2460
|
+
clearInterval(this.keepaliveInterval);
|
|
2461
|
+
this.keepaliveInterval = null;
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
shutdown(reason = "completed") {
|
|
2465
|
+
this.stopKeepalive();
|
|
2466
|
+
for (const [, pending] of this.pendingPermissions) {
|
|
2467
|
+
if (pending.ackTimeout) {
|
|
2468
|
+
clearTimeout(pending.ackTimeout);
|
|
2469
|
+
}
|
|
2470
|
+
if (pending.responseTimeout) {
|
|
2471
|
+
clearTimeout(pending.responseTimeout);
|
|
2472
|
+
}
|
|
2473
|
+
pending.reject(new Error("Adapter shutdown"));
|
|
2474
|
+
}
|
|
2475
|
+
this.pendingPermissions.clear();
|
|
2476
|
+
for (const [, pending] of this.pendingVscodeInvocations) {
|
|
2477
|
+
pending.reject(new Error("Adapter shutdown"));
|
|
2478
|
+
}
|
|
2479
|
+
this.pendingVscodeInvocations.clear();
|
|
2480
|
+
if (this.abortController) {
|
|
2481
|
+
this.abortController.abort();
|
|
2482
|
+
}
|
|
2483
|
+
writeNotification(RPC_NOTIFICATIONS.AGENT_END, {
|
|
2484
|
+
sessionId: this.sessionId,
|
|
2485
|
+
reason,
|
|
2486
|
+
timestamp: createTimestamp()
|
|
2487
|
+
});
|
|
2488
|
+
}
|
|
2489
|
+
/**
|
|
2490
|
+
* Handle output events from the agent
|
|
2491
|
+
*/
|
|
2492
|
+
handleAgentOutput(event) {
|
|
2493
|
+
process.stderr.write(`[RPC DEBUG] handleAgentOutput: type=${event.type}, content length=${event.content?.length ?? 0}
|
|
2494
|
+
`);
|
|
2495
|
+
switch (event.type) {
|
|
2496
|
+
case "thinking":
|
|
2497
|
+
if (event.thought) {
|
|
2498
|
+
process.stderr.write(`[RPC DEBUG] Emitting thinking: ${event.thought.substring(0, 50)}...
|
|
2499
|
+
`);
|
|
2500
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
2501
|
+
messageId: this.currentMessageId,
|
|
2502
|
+
delta: "",
|
|
2503
|
+
thought: event.thought,
|
|
2504
|
+
timestamp: createTimestamp()
|
|
2505
|
+
});
|
|
2506
|
+
}
|
|
2507
|
+
break;
|
|
2508
|
+
case "message":
|
|
2509
|
+
if (event.content) {
|
|
2510
|
+
process.stderr.write(`[RPC DEBUG] Emitting message content: ${event.content.substring(0, 100)}...
|
|
2511
|
+
`);
|
|
2512
|
+
this.currentMessageContent = event.content;
|
|
2513
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
2514
|
+
messageId: this.currentMessageId,
|
|
2515
|
+
delta: event.content,
|
|
2516
|
+
timestamp: createTimestamp()
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
break;
|
|
2520
|
+
case "tool_start":
|
|
2521
|
+
if (event.toolName) {
|
|
2522
|
+
writeNotification(RPC_NOTIFICATIONS.TOOL_START, {
|
|
2523
|
+
toolId: event.toolId ?? generateId("tool"),
|
|
2524
|
+
toolName: event.toolName,
|
|
2525
|
+
args: event.toolArgs ?? {},
|
|
2526
|
+
timestamp: createTimestamp()
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
break;
|
|
2530
|
+
case "tool_end":
|
|
2531
|
+
if (event.toolName) {
|
|
2532
|
+
writeNotification(RPC_NOTIFICATIONS.TOOL_END, {
|
|
2533
|
+
toolId: event.toolId ?? "unknown",
|
|
2534
|
+
toolName: event.toolName,
|
|
2535
|
+
success: event.toolSuccess ?? true,
|
|
2536
|
+
output: event.toolOutput,
|
|
2537
|
+
timestamp: createTimestamp()
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
break;
|
|
2541
|
+
case "schedule_triggered":
|
|
2542
|
+
writeNotification(RPC_NOTIFICATIONS.SCHEDULE_TRIGGERED, {
|
|
2543
|
+
prompt: event.content,
|
|
2544
|
+
scheduleId: event.scheduleId,
|
|
2545
|
+
timestamp: createTimestamp()
|
|
2546
|
+
});
|
|
2547
|
+
break;
|
|
2548
|
+
case "file_modified":
|
|
2549
|
+
if (event.filePath) {
|
|
2550
|
+
writeNotification(RPC_NOTIFICATIONS.HOOK_FILE_MODIFIED, {
|
|
2551
|
+
filePath: event.filePath,
|
|
2552
|
+
changeType: event.changeType ?? "modify",
|
|
2553
|
+
toolId: event.toolId ?? "",
|
|
2554
|
+
timestamp: createTimestamp()
|
|
2555
|
+
});
|
|
2556
|
+
}
|
|
2557
|
+
break;
|
|
2558
|
+
case "error":
|
|
2559
|
+
if (event.content) {
|
|
2560
|
+
process.stderr.write(`[RPC DEBUG] Emitting error: ${event.content.substring(0, 100)}...
|
|
2561
|
+
`);
|
|
2562
|
+
const errorType = this.classifyError(event.content);
|
|
2563
|
+
const icon = errorType.icon;
|
|
2564
|
+
this.currentMessageContent = `${icon} ${event.content}`;
|
|
2565
|
+
writeNotification(RPC_NOTIFICATIONS.MESSAGE_UPDATE, {
|
|
2566
|
+
messageId: this.currentMessageId,
|
|
2567
|
+
delta: this.currentMessageContent,
|
|
2568
|
+
timestamp: createTimestamp()
|
|
2569
|
+
});
|
|
2570
|
+
writeNotification(RPC_NOTIFICATIONS.ERROR, {
|
|
2571
|
+
code: errorType.code,
|
|
2572
|
+
message: event.content,
|
|
2573
|
+
errorType: errorType.type,
|
|
2574
|
+
recoverable: errorType.recoverable,
|
|
2575
|
+
timestamp: createTimestamp()
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2578
|
+
break;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
/**
|
|
2582
|
+
* Classify error messages for appropriate UI treatment.
|
|
2583
|
+
* Delegates to the shared classifyApiError() and maps the result
|
|
2584
|
+
* to the RPC-specific shape (type, code, icon, recoverable).
|
|
2585
|
+
*/
|
|
2586
|
+
classifyError(message) {
|
|
2587
|
+
const classified = classifyApiError(0, message);
|
|
2588
|
+
return {
|
|
2589
|
+
type: RPC_ERROR_TYPE_MAP[classified.code] ?? "unknown",
|
|
2590
|
+
code: RPC_ERROR_CODE_MAP[classified.code] ?? -32e3,
|
|
2591
|
+
icon: RPC_ERROR_ICON_MAP[classified.code] ?? "\u26A0\uFE0F",
|
|
2592
|
+
recoverable: classified.retryable
|
|
2593
|
+
};
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Convert LLMMessage to RpcMessage
|
|
2597
|
+
*/
|
|
2598
|
+
convertMessage(msg, index) {
|
|
2599
|
+
let toolCalls;
|
|
2600
|
+
if (msg.tool_calls && msg.tool_calls.length > 0) {
|
|
2601
|
+
toolCalls = msg.tool_calls.map((tc) => {
|
|
2602
|
+
let args = {};
|
|
2603
|
+
try {
|
|
2604
|
+
if (tc.function?.arguments) {
|
|
2605
|
+
args = JSON.parse(tc.function.arguments);
|
|
2606
|
+
}
|
|
2607
|
+
} catch {
|
|
2608
|
+
}
|
|
2609
|
+
return {
|
|
2610
|
+
id: tc.id,
|
|
2611
|
+
name: tc.function?.name ?? "unknown",
|
|
2612
|
+
args
|
|
2613
|
+
};
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
return {
|
|
2617
|
+
id: `msg_${index}`,
|
|
2618
|
+
role: msg.role,
|
|
2619
|
+
content: msg.content,
|
|
2620
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2621
|
+
toolCalls
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2624
|
+
// ============================================================================
|
|
2625
|
+
// Auto-Mode RPC Handlers
|
|
2626
|
+
// ============================================================================
|
|
2627
|
+
/**
|
|
2628
|
+
* Start auto-mode loop
|
|
2629
|
+
*/
|
|
2630
|
+
async handleAutomodeStart(requestId, params) {
|
|
2631
|
+
try {
|
|
2632
|
+
const automodeManager = this.agent?.getAutomodeManager?.();
|
|
2633
|
+
if (!automodeManager) {
|
|
2634
|
+
return {
|
|
2635
|
+
success: false,
|
|
2636
|
+
error: "Auto-mode manager not available"
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
if (automodeManager.isActive()) {
|
|
2640
|
+
return {
|
|
2641
|
+
success: false,
|
|
2642
|
+
error: "Auto-mode is already running"
|
|
2643
|
+
};
|
|
2644
|
+
}
|
|
2645
|
+
process.stderr.write(`[RPC] Auto-mode start requested: ${params.prompt}
|
|
2646
|
+
`);
|
|
2647
|
+
return {
|
|
2648
|
+
success: true,
|
|
2649
|
+
sessionId: `automode-${Date.now()}`
|
|
2650
|
+
};
|
|
2651
|
+
} catch (error) {
|
|
2652
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2653
|
+
return {
|
|
2654
|
+
success: false,
|
|
2655
|
+
error: message
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
/**
|
|
2660
|
+
* Get auto-mode status
|
|
2661
|
+
*/
|
|
2662
|
+
handleAutomodeStatus(_requestId) {
|
|
2663
|
+
const automodeManager = this.agent?.getAutomodeManager?.();
|
|
2664
|
+
if (!automodeManager) {
|
|
2665
|
+
return {
|
|
2666
|
+
active: false,
|
|
2667
|
+
paused: false
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2670
|
+
const state = automodeManager.getState();
|
|
2671
|
+
return {
|
|
2672
|
+
active: automodeManager.isActive(),
|
|
2673
|
+
paused: automodeManager.isPausedState(),
|
|
2674
|
+
state: state ? {
|
|
2675
|
+
sessionId: state.sessionId,
|
|
2676
|
+
status: state.status,
|
|
2677
|
+
currentIteration: state.currentIteration,
|
|
2678
|
+
maxIterations: state.maxIterations,
|
|
2679
|
+
filesCreated: state.filesCreated,
|
|
2680
|
+
filesModified: state.filesModified,
|
|
2681
|
+
branch: state.branch,
|
|
2682
|
+
lastCheckpoint: state.lastCheckpoint
|
|
2683
|
+
} : void 0
|
|
2684
|
+
};
|
|
2685
|
+
}
|
|
2686
|
+
/**
|
|
2687
|
+
* Pause auto-mode loop
|
|
2688
|
+
*/
|
|
2689
|
+
async handleAutomodePause(_requestId) {
|
|
2690
|
+
try {
|
|
2691
|
+
const automodeManager = this.agent?.getAutomodeManager?.();
|
|
2692
|
+
if (!automodeManager) {
|
|
2693
|
+
return {
|
|
2694
|
+
success: false,
|
|
2695
|
+
error: "Auto-mode manager not available"
|
|
2696
|
+
};
|
|
2697
|
+
}
|
|
2698
|
+
if (!automodeManager.isActive()) {
|
|
2699
|
+
return {
|
|
2700
|
+
success: false,
|
|
2701
|
+
error: "No auto-mode session is running"
|
|
2702
|
+
};
|
|
2703
|
+
}
|
|
2704
|
+
if (automodeManager.isPausedState()) {
|
|
2705
|
+
return {
|
|
2706
|
+
success: false,
|
|
2707
|
+
error: "Auto-mode is already paused"
|
|
2708
|
+
};
|
|
2709
|
+
}
|
|
2710
|
+
await automodeManager.pause();
|
|
2711
|
+
return { success: true };
|
|
2712
|
+
} catch (error) {
|
|
2713
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2714
|
+
return {
|
|
2715
|
+
success: false,
|
|
2716
|
+
error: message
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Resume auto-mode loop
|
|
2722
|
+
*/
|
|
2723
|
+
async handleAutomodeResume(_requestId) {
|
|
2724
|
+
try {
|
|
2725
|
+
const automodeManager = this.agent?.getAutomodeManager?.();
|
|
2726
|
+
if (!automodeManager) {
|
|
2727
|
+
return {
|
|
2728
|
+
success: false,
|
|
2729
|
+
error: "Auto-mode manager not available"
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
if (!automodeManager.isActive()) {
|
|
2733
|
+
return {
|
|
2734
|
+
success: false,
|
|
2735
|
+
error: "No auto-mode session to resume"
|
|
2736
|
+
};
|
|
2737
|
+
}
|
|
2738
|
+
if (!automodeManager.isPausedState()) {
|
|
2739
|
+
return {
|
|
2740
|
+
success: false,
|
|
2741
|
+
error: "Auto-mode is not paused"
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
await automodeManager.resume();
|
|
2745
|
+
return { success: true };
|
|
2746
|
+
} catch (error) {
|
|
2747
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2748
|
+
return {
|
|
2749
|
+
success: false,
|
|
2750
|
+
error: message
|
|
2751
|
+
};
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
/**
|
|
2755
|
+
* Cancel auto-mode loop
|
|
2756
|
+
*/
|
|
2757
|
+
async handleAutomodeCancel(requestId, reason) {
|
|
2758
|
+
try {
|
|
2759
|
+
const automodeManager = this.agent?.getAutomodeManager?.();
|
|
2760
|
+
if (!automodeManager) {
|
|
2761
|
+
return {
|
|
2762
|
+
success: false,
|
|
2763
|
+
error: "Auto-mode manager not available"
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
if (!automodeManager.isActive()) {
|
|
2767
|
+
return {
|
|
2768
|
+
success: false,
|
|
2769
|
+
error: "No auto-mode session to cancel"
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
await automodeManager.cancel(reason || "rpc_cancel");
|
|
2773
|
+
return { success: true };
|
|
2774
|
+
} catch (error) {
|
|
2775
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2776
|
+
return {
|
|
2777
|
+
success: false,
|
|
2778
|
+
error: message
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
/**
|
|
2783
|
+
* Get auto-mode iteration log
|
|
2784
|
+
*/
|
|
2785
|
+
handleAutomodeGetLog(requestId, limit) {
|
|
2786
|
+
try {
|
|
2787
|
+
const automodeManager = this.agent?.getAutomodeManager?.();
|
|
2788
|
+
if (!automodeManager) {
|
|
2789
|
+
return {
|
|
2790
|
+
success: false,
|
|
2791
|
+
iterations: [],
|
|
2792
|
+
error: "Auto-mode manager not available"
|
|
2793
|
+
};
|
|
2794
|
+
}
|
|
2795
|
+
const state = automodeManager.getState();
|
|
2796
|
+
if (!state) {
|
|
2797
|
+
return {
|
|
2798
|
+
success: true,
|
|
2799
|
+
iterations: []
|
|
2800
|
+
};
|
|
2801
|
+
}
|
|
2802
|
+
const iterations = [];
|
|
2803
|
+
return {
|
|
2804
|
+
success: true,
|
|
2805
|
+
iterations: limit ? iterations.slice(-limit) : iterations
|
|
2806
|
+
};
|
|
2807
|
+
} catch (error) {
|
|
2808
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2809
|
+
return {
|
|
2810
|
+
success: false,
|
|
2811
|
+
iterations: [],
|
|
2812
|
+
error: message
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
// ============================================================================
|
|
2817
|
+
// SDK Control RPC Methods
|
|
2818
|
+
// ============================================================================
|
|
2819
|
+
/**
|
|
2820
|
+
* Set permission mode
|
|
2821
|
+
*/
|
|
2822
|
+
async handleSetPermissionMode(params) {
|
|
2823
|
+
try {
|
|
2824
|
+
const previousMode = this.config?.permissionMode || "default";
|
|
2825
|
+
this.config.permissionMode = params.mode;
|
|
2826
|
+
return {
|
|
2827
|
+
success: true,
|
|
2828
|
+
currentMode: params.mode,
|
|
2829
|
+
previousMode
|
|
2830
|
+
};
|
|
2831
|
+
} catch {
|
|
2832
|
+
return {
|
|
2833
|
+
success: false,
|
|
2834
|
+
currentMode: this.config?.permissionMode || "default",
|
|
2835
|
+
previousMode: this.config?.permissionMode || "default"
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
/**
|
|
2840
|
+
* Set model
|
|
2841
|
+
*/
|
|
2842
|
+
async handleSetModel(params) {
|
|
2843
|
+
try {
|
|
2844
|
+
this.config.model = params.model;
|
|
2845
|
+
return {
|
|
2846
|
+
success: true,
|
|
2847
|
+
currentModel: params.model
|
|
2848
|
+
};
|
|
2849
|
+
} catch {
|
|
2850
|
+
return {
|
|
2851
|
+
success: false,
|
|
2852
|
+
currentModel: this.config?.model
|
|
2853
|
+
};
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* Set max thinking tokens
|
|
2858
|
+
*/
|
|
2859
|
+
async handleSetMaxThinkingTokens(params) {
|
|
2860
|
+
try {
|
|
2861
|
+
this.config.maxThinkingTokens = params.maxThinkingTokens ?? void 0;
|
|
2862
|
+
return {
|
|
2863
|
+
success: true,
|
|
2864
|
+
currentMaxThinkingTokens: params.maxThinkingTokens ?? null
|
|
2865
|
+
};
|
|
2866
|
+
} catch {
|
|
2867
|
+
return {
|
|
2868
|
+
success: false,
|
|
2869
|
+
currentMaxThinkingTokens: this.config?.maxThinkingTokens || null
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
/**
|
|
2874
|
+
* Apply flag settings — now propagates contextCompact to the agent.
|
|
2875
|
+
*/
|
|
2876
|
+
async handleApplyFlagSettings(params) {
|
|
2877
|
+
try {
|
|
2878
|
+
const appliedSettings = [];
|
|
2879
|
+
for (const [key, value] of Object.entries(params.settings)) {
|
|
2880
|
+
if (value !== void 0) {
|
|
2881
|
+
this.config[key] = value;
|
|
2882
|
+
appliedSettings.push(key);
|
|
2883
|
+
if (key === "contextCompact" && typeof value === "boolean") {
|
|
2884
|
+
this.agent?.setContextCompaction(value);
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
return {
|
|
2889
|
+
success: true,
|
|
2890
|
+
appliedSettings
|
|
2891
|
+
};
|
|
2892
|
+
} catch {
|
|
2893
|
+
return {
|
|
2894
|
+
success: false,
|
|
2895
|
+
appliedSettings: []
|
|
2896
|
+
};
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
/**
|
|
2900
|
+
* Get supported models
|
|
2901
|
+
*/
|
|
2902
|
+
async handleGetSupportedModels() {
|
|
2903
|
+
try {
|
|
2904
|
+
const models = [
|
|
2905
|
+
{ id: "anthropic/claude-sonnet-4", displayName: "Claude Sonnet 4" },
|
|
2906
|
+
{ id: "anthropic/claude-3-5-sonnet-20241022", displayName: "Claude 3.5 Sonnet" },
|
|
2907
|
+
{ id: "openai/gpt-4o", displayName: "GPT-4o" },
|
|
2908
|
+
{ id: "openai/gpt-4o-mini", displayName: "GPT-4o Mini" }
|
|
2909
|
+
];
|
|
2910
|
+
return {
|
|
2911
|
+
models
|
|
2912
|
+
};
|
|
2913
|
+
} catch {
|
|
2914
|
+
return {
|
|
2915
|
+
models: []
|
|
2916
|
+
};
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
/**
|
|
2920
|
+
* Get supported commands
|
|
2921
|
+
*/
|
|
2922
|
+
async handleGetSupportedCommands() {
|
|
2923
|
+
try {
|
|
2924
|
+
const commands = [
|
|
2925
|
+
"help",
|
|
2926
|
+
"model",
|
|
2927
|
+
"auto",
|
|
2928
|
+
"plan",
|
|
2929
|
+
"skills",
|
|
2930
|
+
"learn",
|
|
2931
|
+
"mcp",
|
|
2932
|
+
"chrome"
|
|
2933
|
+
];
|
|
2934
|
+
return {
|
|
2935
|
+
commands
|
|
2936
|
+
};
|
|
2937
|
+
} catch {
|
|
2938
|
+
return {
|
|
2939
|
+
commands: []
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
/**
|
|
2944
|
+
* Get context usage — returns real data from the agent's orchestrator.
|
|
2945
|
+
*/
|
|
2946
|
+
async handleGetContextUsage() {
|
|
2947
|
+
try {
|
|
2948
|
+
if (this.agent?.getContextOrchestrator) {
|
|
2949
|
+
const orchestrator = this.agent.getContextOrchestrator();
|
|
2950
|
+
const tools = this.agent.getToolDefinitions?.() ?? [];
|
|
2951
|
+
const usage = orchestrator.getExtendedUsage(tools);
|
|
2952
|
+
return {
|
|
2953
|
+
systemPrompt: usage.systemPrompt,
|
|
2954
|
+
tools: usage.tools,
|
|
2955
|
+
messages: usage.messages,
|
|
2956
|
+
mcpTools: usage.mcpTools,
|
|
2957
|
+
memoryFiles: usage.memoryFiles,
|
|
2958
|
+
total: usage.total,
|
|
2959
|
+
contextWindow: usage.contextWindow,
|
|
2960
|
+
usagePercent: usage.usagePercent,
|
|
2961
|
+
isWarning: usage.isWarning,
|
|
2962
|
+
isCritical: usage.isCritical
|
|
2963
|
+
};
|
|
2964
|
+
}
|
|
2965
|
+
return {
|
|
2966
|
+
systemPrompt: 0,
|
|
2967
|
+
tools: 0,
|
|
2968
|
+
messages: 0,
|
|
2969
|
+
mcpTools: 0,
|
|
2970
|
+
memoryFiles: 0,
|
|
2971
|
+
total: 0
|
|
2972
|
+
};
|
|
2973
|
+
} catch {
|
|
2974
|
+
return {
|
|
2975
|
+
systemPrompt: 0,
|
|
2976
|
+
tools: 0,
|
|
2977
|
+
messages: 0,
|
|
2978
|
+
mcpTools: 0,
|
|
2979
|
+
memoryFiles: 0,
|
|
2980
|
+
total: 0
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
/**
|
|
2985
|
+
* Set context compaction enabled/disabled
|
|
2986
|
+
*/
|
|
2987
|
+
async handleSetContextCompact(params) {
|
|
2988
|
+
try {
|
|
2989
|
+
this.agent?.setContextCompaction(params.enabled);
|
|
2990
|
+
return { enabled: params.enabled };
|
|
2991
|
+
} catch {
|
|
2992
|
+
return { enabled: this.agent?.isContextCompactionEnabled?.() ?? false };
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
/**
|
|
2996
|
+
* Reload plugins
|
|
2997
|
+
*/
|
|
2998
|
+
async handleReloadPlugins() {
|
|
2999
|
+
try {
|
|
3000
|
+
const reloadedPlugins = ["skills"];
|
|
3001
|
+
return {
|
|
3002
|
+
success: true,
|
|
3003
|
+
reloadedPlugins
|
|
3004
|
+
};
|
|
3005
|
+
} catch {
|
|
3006
|
+
return {
|
|
3007
|
+
success: false,
|
|
3008
|
+
reloadedPlugins: []
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
3013
|
+
* Get account info
|
|
3014
|
+
*/
|
|
3015
|
+
async handleGetAccountInfo() {
|
|
3016
|
+
try {
|
|
3017
|
+
return {
|
|
3018
|
+
email: "user@example.com"
|
|
3019
|
+
};
|
|
3020
|
+
} catch {
|
|
3021
|
+
return {
|
|
3022
|
+
email: ""
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
/**
|
|
3027
|
+
* Toggle MCP server
|
|
3028
|
+
*/
|
|
3029
|
+
async handleMcpToggleServer(params) {
|
|
3030
|
+
try {
|
|
3031
|
+
return {
|
|
3032
|
+
success: true,
|
|
3033
|
+
serverName: params.serverName,
|
|
3034
|
+
status: params.enabled ? "enabled" : "disabled"
|
|
3035
|
+
};
|
|
3036
|
+
} catch {
|
|
3037
|
+
return {
|
|
3038
|
+
success: false,
|
|
3039
|
+
serverName: params.serverName,
|
|
3040
|
+
status: "disabled"
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
/**
|
|
3045
|
+
* Reconnect MCP server
|
|
3046
|
+
*/
|
|
3047
|
+
async handleMcpReconnectServer(params) {
|
|
3048
|
+
try {
|
|
3049
|
+
return {
|
|
3050
|
+
success: true,
|
|
3051
|
+
serverName: params.serverName,
|
|
3052
|
+
status: "connected"
|
|
3053
|
+
};
|
|
3054
|
+
} catch {
|
|
3055
|
+
return {
|
|
3056
|
+
success: false,
|
|
3057
|
+
serverName: params.serverName,
|
|
3058
|
+
status: "disconnected"
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
/**
|
|
3063
|
+
* Set MCP servers
|
|
3064
|
+
*/
|
|
3065
|
+
async handleMcpSetServers(params) {
|
|
3066
|
+
try {
|
|
3067
|
+
const configuredServers = Object.keys(params.servers);
|
|
3068
|
+
return {
|
|
3069
|
+
success: true,
|
|
3070
|
+
configuredServers
|
|
3071
|
+
};
|
|
3072
|
+
} catch {
|
|
3073
|
+
return {
|
|
3074
|
+
success: false,
|
|
3075
|
+
configuredServers: []
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
};
|
|
3080
|
+
function parseRpcGoalStatus(value) {
|
|
3081
|
+
if (value === "active" || value === "paused" || value === "complete" || value === "budgetLimited") {
|
|
3082
|
+
return value;
|
|
3083
|
+
}
|
|
3084
|
+
return void 0;
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
// src/modes/rpc/index.ts
|
|
3088
|
+
var originalConsole = {
|
|
3089
|
+
log: console.log,
|
|
3090
|
+
warn: console.warn,
|
|
3091
|
+
error: console.error,
|
|
3092
|
+
info: console.info,
|
|
3093
|
+
debug: console.debug
|
|
3094
|
+
};
|
|
3095
|
+
function suppressConsole() {
|
|
3096
|
+
console.log = () => {
|
|
3097
|
+
};
|
|
3098
|
+
console.warn = () => {
|
|
3099
|
+
};
|
|
3100
|
+
console.error = () => {
|
|
3101
|
+
};
|
|
3102
|
+
console.info = () => {
|
|
3103
|
+
};
|
|
3104
|
+
console.debug = () => {
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
function restoreConsole() {
|
|
3108
|
+
console.log = originalConsole.log;
|
|
3109
|
+
console.warn = originalConsole.warn;
|
|
3110
|
+
console.error = originalConsole.error;
|
|
3111
|
+
console.info = originalConsole.info;
|
|
3112
|
+
console.debug = originalConsole.debug;
|
|
3113
|
+
}
|
|
3114
|
+
async function runRpcMode(options) {
|
|
3115
|
+
suppressConsole();
|
|
3116
|
+
const { setBrowserBridgeOutput } = await import("./browserToolBridge-F5N66PE7.js");
|
|
3117
|
+
setBrowserBridgeOutput(process.stdout);
|
|
3118
|
+
process.stdout.on("error", (err) => {
|
|
3119
|
+
process.stderr.write(`[RPC] stdout error: ${err.message}
|
|
3120
|
+
`);
|
|
3121
|
+
});
|
|
3122
|
+
process.stdin.on("error", (err) => {
|
|
3123
|
+
process.stderr.write(`[RPC] stdin error: ${err.message}
|
|
3124
|
+
`);
|
|
3125
|
+
});
|
|
3126
|
+
process.stdin.on("end", () => {
|
|
3127
|
+
process.stderr.write("[RPC] stdin end (extension disconnected)\n");
|
|
3128
|
+
});
|
|
3129
|
+
let adapter = null;
|
|
3130
|
+
let agent = null;
|
|
3131
|
+
try {
|
|
3132
|
+
const config = await loadConfig(options.config, process.cwd());
|
|
3133
|
+
const normalizedYolo = normalizeYoloInput(options.yolo);
|
|
3134
|
+
if (normalizedYolo) {
|
|
3135
|
+
try {
|
|
3136
|
+
const yoloPattern = parseYoloPattern(normalizedYolo);
|
|
3137
|
+
options.yolo = normalizedYolo;
|
|
3138
|
+
config.permissions = {
|
|
3139
|
+
...config.permissions,
|
|
3140
|
+
...buildPermissionSettingsFromYolo(yoloPattern)
|
|
3141
|
+
};
|
|
3142
|
+
} catch (error) {
|
|
3143
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3144
|
+
writeErrorResponse(null, JSON_RPC_ERROR_CODES.INTERNAL_ERROR, message);
|
|
3145
|
+
process.exit(1);
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
const originalWorkspaceRoot = options.path ?? process.cwd();
|
|
3149
|
+
let workspaceRoot = originalWorkspaceRoot;
|
|
3150
|
+
const workspacePathValidation = await validateWorkspacePath(originalWorkspaceRoot);
|
|
3151
|
+
if (!workspacePathValidation.valid) {
|
|
3152
|
+
writeErrorResponse(
|
|
3153
|
+
null,
|
|
3154
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
3155
|
+
workspacePathValidation.error || "Invalid workspace path"
|
|
3156
|
+
);
|
|
3157
|
+
process.exit(1);
|
|
3158
|
+
}
|
|
3159
|
+
const safetyCheck = checkWorkspaceSafety(originalWorkspaceRoot);
|
|
3160
|
+
if (!safetyCheck.safe) {
|
|
3161
|
+
writeErrorResponse(
|
|
3162
|
+
null,
|
|
3163
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
3164
|
+
`Unsafe workspace: ${safetyCheck.reason || originalWorkspaceRoot}`
|
|
3165
|
+
);
|
|
3166
|
+
process.exit(1);
|
|
3167
|
+
}
|
|
3168
|
+
const isAuthed = await checkAuthenticated(config);
|
|
3169
|
+
if (!isAuthed) {
|
|
3170
|
+
writeErrorResponse(
|
|
3171
|
+
null,
|
|
3172
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
3173
|
+
"Authentication required. Run `autohand login` first."
|
|
3174
|
+
);
|
|
3175
|
+
process.exit(1);
|
|
3176
|
+
}
|
|
3177
|
+
if (!config.ui) {
|
|
3178
|
+
config.ui = {};
|
|
3179
|
+
}
|
|
3180
|
+
config.ui.useInkRenderer = false;
|
|
3181
|
+
if (isSessionWorktreeEnabled(options.worktree)) {
|
|
3182
|
+
const sessionWorktree = prepareSessionWorktree({
|
|
3183
|
+
cwd: originalWorkspaceRoot,
|
|
3184
|
+
worktree: options.worktree,
|
|
3185
|
+
mode: "rpc"
|
|
3186
|
+
});
|
|
3187
|
+
workspaceRoot = sessionWorktree.worktreePath;
|
|
3188
|
+
process.stderr.write(`[RPC] Using git worktree ${sessionWorktree.worktreePath} (${sessionWorktree.branchName})
|
|
3189
|
+
`);
|
|
3190
|
+
}
|
|
3191
|
+
const additionalDirs = [];
|
|
3192
|
+
if (options.addDir && options.addDir.length > 0) {
|
|
3193
|
+
for (const dir of options.addDir) {
|
|
3194
|
+
const resolvedDir = path.resolve(dir);
|
|
3195
|
+
if (!await fs.pathExists(resolvedDir)) {
|
|
3196
|
+
throw new Error(`Additional directory does not exist: ${dir}`);
|
|
3197
|
+
}
|
|
3198
|
+
const stats = await fs.stat(resolvedDir);
|
|
3199
|
+
if (!stats.isDirectory()) {
|
|
3200
|
+
throw new Error(`Additional path is not a directory: ${dir}`);
|
|
3201
|
+
}
|
|
3202
|
+
const addDirSafetyCheck = checkWorkspaceSafety(resolvedDir);
|
|
3203
|
+
if (!addDirSafetyCheck.safe) {
|
|
3204
|
+
throw new Error(`Unsafe additional directory: ${dir} - ${addDirSafetyCheck.reason}`);
|
|
3205
|
+
}
|
|
3206
|
+
additionalDirs.push(resolvedDir);
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
3209
|
+
const runtime = {
|
|
3210
|
+
config,
|
|
3211
|
+
workspaceRoot,
|
|
3212
|
+
options: {
|
|
3213
|
+
...options,
|
|
3214
|
+
clientContext: "chrome"
|
|
3215
|
+
// Do NOT set yes: true - permissions are handled via RPC
|
|
3216
|
+
},
|
|
3217
|
+
additionalDirs: additionalDirs.length > 0 ? additionalDirs : void 0,
|
|
3218
|
+
isRpcMode: true
|
|
3219
|
+
};
|
|
3220
|
+
const provider = ProviderFactory.create(config);
|
|
3221
|
+
if (options.model) {
|
|
3222
|
+
provider.setModel(options.model);
|
|
3223
|
+
}
|
|
3224
|
+
const files = new FileActionManager(workspaceRoot, additionalDirs);
|
|
3225
|
+
agent = new AutohandAgent(provider, files, runtime);
|
|
3226
|
+
await agent.initializeForRPC();
|
|
3227
|
+
const conversation = ConversationManager.getInstance();
|
|
3228
|
+
try {
|
|
3229
|
+
const { CHROME_AUTOMATION_SYSTEM_PROMPT } = await import("./chromeSkill-53TH55PM.js");
|
|
3230
|
+
conversation.addSystemNote(CHROME_AUTOMATION_SYSTEM_PROMPT);
|
|
3231
|
+
} catch {
|
|
3232
|
+
}
|
|
3233
|
+
adapter = new RPCAdapter();
|
|
3234
|
+
adapter.initialize(
|
|
3235
|
+
agent,
|
|
3236
|
+
conversation,
|
|
3237
|
+
options.model ?? config.openrouter?.model ?? "unknown",
|
|
3238
|
+
workspaceRoot,
|
|
3239
|
+
config,
|
|
3240
|
+
config.mcp?.servers
|
|
3241
|
+
);
|
|
3242
|
+
agent.setConfirmationCallback(async (message, context) => {
|
|
3243
|
+
if (!adapter) {
|
|
3244
|
+
throw new Error("RPC adapter not initialized");
|
|
3245
|
+
}
|
|
3246
|
+
const tool = context?.tool ?? "action";
|
|
3247
|
+
const description = message;
|
|
3248
|
+
const permContext = {};
|
|
3249
|
+
if (context?.command) permContext.command = context.command;
|
|
3250
|
+
if (context?.path) permContext.path = context.path;
|
|
3251
|
+
return adapter.requestPermission(tool, description, permContext);
|
|
3252
|
+
});
|
|
3253
|
+
agent.setDirectoryAccessCallback(async (path2, reason) => {
|
|
3254
|
+
if (!adapter) {
|
|
3255
|
+
throw new Error("RPC adapter not initialized");
|
|
3256
|
+
}
|
|
3257
|
+
return adapter.requestDirectoryAccess(path2, reason);
|
|
3258
|
+
});
|
|
3259
|
+
const reader = new LineReader(process.stdin);
|
|
3260
|
+
while (true) {
|
|
3261
|
+
try {
|
|
3262
|
+
const line = await reader.readLine();
|
|
3263
|
+
process.stderr.write(`[RPC DEBUG] stdin read line size=${line.length}b
|
|
3264
|
+
`);
|
|
3265
|
+
await handleLine(line, adapter);
|
|
3266
|
+
} catch (error) {
|
|
3267
|
+
if (error instanceof Error && error.message === "Stream closed") {
|
|
3268
|
+
process.stderr.write("[RPC] Extension disconnected (stdin closed). Shutting down gracefully.\n");
|
|
3269
|
+
break;
|
|
3270
|
+
}
|
|
3271
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3272
|
+
process.stderr.write(`[RPC] Fatal error in request loop: ${message}
|
|
3273
|
+
`);
|
|
3274
|
+
writeInternalError(null, message);
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
adapter?.shutdown("disconnected");
|
|
3278
|
+
process.exit(0);
|
|
3279
|
+
} catch (error) {
|
|
3280
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3281
|
+
writeErrorResponse(null, JSON_RPC_ERROR_CODES.INTERNAL_ERROR, `Initialization error: ${message}`);
|
|
3282
|
+
adapter?.shutdown("error");
|
|
3283
|
+
process.exit(1);
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
async function handleLine(line, adapter) {
|
|
3287
|
+
process.stderr.write(`[RPC DEBUG] handleLine received: ${line.slice(0, 100)}
|
|
3288
|
+
`);
|
|
3289
|
+
const parseResult = parseRequest(line);
|
|
3290
|
+
if (parseResult.type === "error") {
|
|
3291
|
+
writeErrorResponse(null, parseResult.code, parseResult.message);
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
if (parseResult.type === "batch") {
|
|
3295
|
+
const responses = await Promise.all(
|
|
3296
|
+
parseResult.requests.map((req) => handleSingleRequest(req, adapter))
|
|
3297
|
+
);
|
|
3298
|
+
const validResponses = responses.filter((r) => r !== null);
|
|
3299
|
+
writeBatchResponse(validResponses);
|
|
3300
|
+
return;
|
|
3301
|
+
}
|
|
3302
|
+
const response = await handleSingleRequest(parseResult.request, adapter);
|
|
3303
|
+
if (response !== null) {
|
|
3304
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
async function handleSingleRequest(request, adapter) {
|
|
3308
|
+
const { method, params, id } = request;
|
|
3309
|
+
const shouldRespond = !isNotification(request);
|
|
3310
|
+
try {
|
|
3311
|
+
let result;
|
|
3312
|
+
switch (method) {
|
|
3313
|
+
case RPC_METHODS.PROMPT: {
|
|
3314
|
+
const promptParams = params;
|
|
3315
|
+
if (!promptParams?.message) {
|
|
3316
|
+
if (shouldRespond) {
|
|
3317
|
+
return createErrorResponse(
|
|
3318
|
+
id,
|
|
3319
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3320
|
+
"Missing required parameter: message"
|
|
3321
|
+
);
|
|
3322
|
+
}
|
|
3323
|
+
return null;
|
|
3324
|
+
}
|
|
3325
|
+
adapter.handlePrompt(id, promptParams).then((promptResult) => {
|
|
3326
|
+
if (shouldRespond) {
|
|
3327
|
+
process.stdout.write(JSON.stringify(createResponse(id, promptResult)) + "\n");
|
|
3328
|
+
}
|
|
3329
|
+
}).catch((error) => {
|
|
3330
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3331
|
+
if (shouldRespond) {
|
|
3332
|
+
process.stdout.write(JSON.stringify(createErrorResponse(
|
|
3333
|
+
id,
|
|
3334
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
3335
|
+
message
|
|
3336
|
+
)) + "\n");
|
|
3337
|
+
}
|
|
3338
|
+
});
|
|
3339
|
+
return null;
|
|
3340
|
+
}
|
|
3341
|
+
case RPC_METHODS.ABORT: {
|
|
3342
|
+
process.stderr.write(`[RPC DEBUG] ABORT received! id=${id}, isNotification=${!shouldRespond}
|
|
3343
|
+
`);
|
|
3344
|
+
result = adapter.handleAbort(id ?? null);
|
|
3345
|
+
break;
|
|
3346
|
+
}
|
|
3347
|
+
case RPC_METHODS.RESET: {
|
|
3348
|
+
result = await adapter.handleReset(id);
|
|
3349
|
+
break;
|
|
3350
|
+
}
|
|
3351
|
+
case RPC_METHODS.GET_STATE: {
|
|
3352
|
+
result = adapter.handleGetState(id);
|
|
3353
|
+
break;
|
|
3354
|
+
}
|
|
3355
|
+
case RPC_METHODS.GET_MESSAGES: {
|
|
3356
|
+
const messagesParams = params;
|
|
3357
|
+
result = adapter.handleGetMessages(id, messagesParams?.limit);
|
|
3358
|
+
break;
|
|
3359
|
+
}
|
|
3360
|
+
case RPC_METHODS.BROWSER_HANDOFF_CREATE: {
|
|
3361
|
+
const handoffCreateParams = params;
|
|
3362
|
+
result = await adapter.handleBrowserHandoffCreate(id, handoffCreateParams);
|
|
3363
|
+
break;
|
|
3364
|
+
}
|
|
3365
|
+
case RPC_METHODS.BROWSER_HANDOFF_ATTACH: {
|
|
3366
|
+
const handoffAttachParams = params;
|
|
3367
|
+
if (!handoffAttachParams?.token) {
|
|
3368
|
+
if (shouldRespond) {
|
|
3369
|
+
return createErrorResponse(
|
|
3370
|
+
id,
|
|
3371
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3372
|
+
"Missing required parameter: token"
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
return null;
|
|
3376
|
+
}
|
|
3377
|
+
result = await adapter.handleBrowserHandoffAttach(id, handoffAttachParams);
|
|
3378
|
+
break;
|
|
3379
|
+
}
|
|
3380
|
+
case RPC_METHODS.BROWSER_HANDOFF_ATTACH_LATEST: {
|
|
3381
|
+
const handoffAttachLatestParams = params;
|
|
3382
|
+
result = await adapter.handleBrowserHandoffAttachLatest(id, handoffAttachLatestParams);
|
|
3383
|
+
break;
|
|
3384
|
+
}
|
|
3385
|
+
case RPC_METHODS.PERMISSION_RESPONSE: {
|
|
3386
|
+
const permParams = params;
|
|
3387
|
+
if (!permParams?.requestId || permParams?.decision === void 0 && permParams?.allowed === void 0) {
|
|
3388
|
+
if (shouldRespond) {
|
|
3389
|
+
return createErrorResponse(
|
|
3390
|
+
id,
|
|
3391
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3392
|
+
"Missing required parameters: requestId and a permission decision"
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3395
|
+
return null;
|
|
3396
|
+
}
|
|
3397
|
+
result = adapter.handlePermissionResponse(
|
|
3398
|
+
id,
|
|
3399
|
+
permParams.requestId,
|
|
3400
|
+
permParams.decision ? { decision: permParams.decision, alternative: permParams.alternative } : Boolean(permParams.allowed)
|
|
3401
|
+
);
|
|
3402
|
+
break;
|
|
3403
|
+
}
|
|
3404
|
+
case RPC_METHODS.PERMISSION_ACKNOWLEDGED: {
|
|
3405
|
+
const ackParams = params;
|
|
3406
|
+
if (!ackParams?.requestId) {
|
|
3407
|
+
if (shouldRespond) {
|
|
3408
|
+
return createErrorResponse(
|
|
3409
|
+
id,
|
|
3410
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3411
|
+
"Missing required parameter: requestId"
|
|
3412
|
+
);
|
|
3413
|
+
}
|
|
3414
|
+
return null;
|
|
3415
|
+
}
|
|
3416
|
+
result = adapter.handlePermissionAcknowledged(ackParams.requestId);
|
|
3417
|
+
break;
|
|
3418
|
+
}
|
|
3419
|
+
case RPC_METHODS.DIRECTORY_ACCESS_RESPONSE: {
|
|
3420
|
+
const dirParams = params;
|
|
3421
|
+
if (!dirParams?.requestId || typeof dirParams.granted !== "boolean") {
|
|
3422
|
+
if (shouldRespond) {
|
|
3423
|
+
return createErrorResponse(
|
|
3424
|
+
id,
|
|
3425
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3426
|
+
"Missing required parameters: requestId, granted"
|
|
3427
|
+
);
|
|
3428
|
+
}
|
|
3429
|
+
return null;
|
|
3430
|
+
}
|
|
3431
|
+
result = adapter.handleDirectoryAccessResponse(dirParams.requestId, dirParams.granted);
|
|
3432
|
+
break;
|
|
3433
|
+
}
|
|
3434
|
+
case RPC_METHODS.DIRECTORY_ACCESS_ACKNOWLEDGED: {
|
|
3435
|
+
const dirAckParams = params;
|
|
3436
|
+
if (!dirAckParams?.requestId) {
|
|
3437
|
+
if (shouldRespond) {
|
|
3438
|
+
return createErrorResponse(
|
|
3439
|
+
id,
|
|
3440
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3441
|
+
"Missing required parameter: requestId"
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
return null;
|
|
3445
|
+
}
|
|
3446
|
+
result = adapter.handleDirectoryAccessAcknowledged(dirAckParams.requestId);
|
|
3447
|
+
break;
|
|
3448
|
+
}
|
|
3449
|
+
case RPC_METHODS.CHANGES_DECISION: {
|
|
3450
|
+
const decisionParams = params;
|
|
3451
|
+
if (!decisionParams?.batchId || !decisionParams?.action) {
|
|
3452
|
+
if (shouldRespond) {
|
|
3453
|
+
return createErrorResponse(
|
|
3454
|
+
id,
|
|
3455
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3456
|
+
"Missing required parameters: batchId, action"
|
|
3457
|
+
);
|
|
3458
|
+
}
|
|
3459
|
+
return null;
|
|
3460
|
+
}
|
|
3461
|
+
result = await adapter.handleChangesDecision(id, decisionParams);
|
|
3462
|
+
break;
|
|
3463
|
+
}
|
|
3464
|
+
case RPC_METHODS.GET_SKILLS_REGISTRY: {
|
|
3465
|
+
const registryParams = params;
|
|
3466
|
+
result = await adapter.handleGetSkillsRegistry(id, registryParams);
|
|
3467
|
+
break;
|
|
3468
|
+
}
|
|
3469
|
+
case RPC_METHODS.INSTALL_SKILL: {
|
|
3470
|
+
const installParams = params;
|
|
3471
|
+
if (!installParams?.skillName || !installParams?.scope) {
|
|
3472
|
+
if (shouldRespond) {
|
|
3473
|
+
return createErrorResponse(
|
|
3474
|
+
id,
|
|
3475
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3476
|
+
"Missing required parameters: skillName, scope"
|
|
3477
|
+
);
|
|
3478
|
+
}
|
|
3479
|
+
return null;
|
|
3480
|
+
}
|
|
3481
|
+
result = await adapter.handleInstallSkill(id, installParams);
|
|
3482
|
+
break;
|
|
3483
|
+
}
|
|
3484
|
+
// Auto-mode RPC methods
|
|
3485
|
+
case RPC_METHODS.AUTOMODE_START: {
|
|
3486
|
+
const startParams = params;
|
|
3487
|
+
if (!startParams?.prompt) {
|
|
3488
|
+
if (shouldRespond) {
|
|
3489
|
+
return createErrorResponse(
|
|
3490
|
+
id,
|
|
3491
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3492
|
+
"Missing required parameter: prompt"
|
|
3493
|
+
);
|
|
3494
|
+
}
|
|
3495
|
+
return null;
|
|
3496
|
+
}
|
|
3497
|
+
result = await adapter.handleAutomodeStart(id, startParams);
|
|
3498
|
+
break;
|
|
3499
|
+
}
|
|
3500
|
+
case RPC_METHODS.AUTOMODE_STATUS: {
|
|
3501
|
+
result = adapter.handleAutomodeStatus(id);
|
|
3502
|
+
break;
|
|
3503
|
+
}
|
|
3504
|
+
case RPC_METHODS.AUTOMODE_PAUSE: {
|
|
3505
|
+
result = await adapter.handleAutomodePause(id);
|
|
3506
|
+
break;
|
|
3507
|
+
}
|
|
3508
|
+
case RPC_METHODS.AUTOMODE_RESUME: {
|
|
3509
|
+
result = await adapter.handleAutomodeResume(id);
|
|
3510
|
+
break;
|
|
3511
|
+
}
|
|
3512
|
+
case RPC_METHODS.AUTOMODE_CANCEL: {
|
|
3513
|
+
const cancelParams = params;
|
|
3514
|
+
result = await adapter.handleAutomodeCancel(id, cancelParams?.reason);
|
|
3515
|
+
break;
|
|
3516
|
+
}
|
|
3517
|
+
case RPC_METHODS.AUTOMODE_GET_LOG: {
|
|
3518
|
+
const logParams = params;
|
|
3519
|
+
result = adapter.handleAutomodeGetLog(id, logParams?.limit);
|
|
3520
|
+
break;
|
|
3521
|
+
}
|
|
3522
|
+
case RPC_METHODS.PLAN_MODE_SET: {
|
|
3523
|
+
const planParams = params;
|
|
3524
|
+
if (planParams?.enabled === void 0) {
|
|
3525
|
+
if (shouldRespond) {
|
|
3526
|
+
return createErrorResponse(
|
|
3527
|
+
id,
|
|
3528
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3529
|
+
"Missing required parameter: enabled"
|
|
3530
|
+
);
|
|
3531
|
+
}
|
|
3532
|
+
return null;
|
|
3533
|
+
}
|
|
3534
|
+
const planModeManager = getPlanModeManager();
|
|
3535
|
+
if (planParams.enabled) {
|
|
3536
|
+
planModeManager.enable();
|
|
3537
|
+
} else {
|
|
3538
|
+
planModeManager.disable();
|
|
3539
|
+
}
|
|
3540
|
+
process.stderr.write(`[RPC DEBUG] Plan mode set to: ${planParams.enabled}
|
|
3541
|
+
`);
|
|
3542
|
+
result = { success: true };
|
|
3543
|
+
break;
|
|
3544
|
+
}
|
|
3545
|
+
case RPC_METHODS.GET_HISTORY: {
|
|
3546
|
+
const historyParams = params;
|
|
3547
|
+
result = await adapter.handleGetHistory(id, historyParams);
|
|
3548
|
+
break;
|
|
3549
|
+
}
|
|
3550
|
+
case RPC_METHODS.GET_SESSION: {
|
|
3551
|
+
result = await adapter.handleGetSession(id, params);
|
|
3552
|
+
break;
|
|
3553
|
+
}
|
|
3554
|
+
case RPC_METHODS.YOLO_SET: {
|
|
3555
|
+
const yoloParams = params;
|
|
3556
|
+
if (!yoloParams?.pattern) {
|
|
3557
|
+
if (shouldRespond) {
|
|
3558
|
+
return createErrorResponse(
|
|
3559
|
+
id,
|
|
3560
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3561
|
+
"Missing required parameter: pattern"
|
|
3562
|
+
);
|
|
3563
|
+
}
|
|
3564
|
+
return null;
|
|
3565
|
+
}
|
|
3566
|
+
result = adapter.handleYoloSet(id, yoloParams);
|
|
3567
|
+
break;
|
|
3568
|
+
}
|
|
3569
|
+
case RPC_METHODS.MCP_LIST_SERVERS: {
|
|
3570
|
+
result = adapter.handleMcpListServers(id);
|
|
3571
|
+
break;
|
|
3572
|
+
}
|
|
3573
|
+
case RPC_METHODS.MCP_LIST_TOOLS: {
|
|
3574
|
+
const mcpToolsParams = params;
|
|
3575
|
+
result = adapter.handleMcpListTools(id, mcpToolsParams);
|
|
3576
|
+
break;
|
|
3577
|
+
}
|
|
3578
|
+
case RPC_METHODS.MCP_SET_VSCODE_TOOLS: {
|
|
3579
|
+
const setToolsParams = params;
|
|
3580
|
+
if (!setToolsParams?.tools) {
|
|
3581
|
+
if (shouldRespond) {
|
|
3582
|
+
return createErrorResponse(
|
|
3583
|
+
id,
|
|
3584
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3585
|
+
"Missing required parameter: tools"
|
|
3586
|
+
);
|
|
3587
|
+
}
|
|
3588
|
+
return null;
|
|
3589
|
+
}
|
|
3590
|
+
result = adapter.handleMcpSetVscodeTools(id, setToolsParams);
|
|
3591
|
+
break;
|
|
3592
|
+
}
|
|
3593
|
+
case RPC_METHODS.MCP_INVOKE_RESPONSE: {
|
|
3594
|
+
const invokeParams = params;
|
|
3595
|
+
if (!invokeParams?.requestId || invokeParams?.success === void 0) {
|
|
3596
|
+
if (shouldRespond) {
|
|
3597
|
+
return createErrorResponse(
|
|
3598
|
+
id,
|
|
3599
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3600
|
+
"Missing required parameters: requestId, success"
|
|
3601
|
+
);
|
|
3602
|
+
}
|
|
3603
|
+
return null;
|
|
3604
|
+
}
|
|
3605
|
+
if (invokeParams.requestId.startsWith("browser_")) {
|
|
3606
|
+
const { resolveBrowserToolResponse } = await import("./browserToolBridge-F5N66PE7.js");
|
|
3607
|
+
const handled = resolveBrowserToolResponse(
|
|
3608
|
+
invokeParams.requestId,
|
|
3609
|
+
invokeParams.success,
|
|
3610
|
+
typeof invokeParams.result === "string" ? invokeParams.result : JSON.stringify(invokeParams.result),
|
|
3611
|
+
invokeParams.error
|
|
3612
|
+
);
|
|
3613
|
+
if (handled) {
|
|
3614
|
+
result = { success: true };
|
|
3615
|
+
break;
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
result = adapter.handleMcpInvokeResponse(id, invokeParams);
|
|
3619
|
+
break;
|
|
3620
|
+
}
|
|
3621
|
+
case RPC_METHODS.MCP_GET_SERVER_CONFIGS: {
|
|
3622
|
+
result = adapter.handleMcpGetServerConfigs(id);
|
|
3623
|
+
break;
|
|
3624
|
+
}
|
|
3625
|
+
// Learn command methods
|
|
3626
|
+
case RPC_METHODS.LEARN_RECOMMEND: {
|
|
3627
|
+
const learnParams = params;
|
|
3628
|
+
result = await adapter.handleLearnRecommend(id, learnParams);
|
|
3629
|
+
break;
|
|
3630
|
+
}
|
|
3631
|
+
case RPC_METHODS.LEARN_UPDATE: {
|
|
3632
|
+
result = await adapter.handleLearnUpdate(id);
|
|
3633
|
+
break;
|
|
3634
|
+
}
|
|
3635
|
+
case RPC_METHODS.LEARN_GENERATE: {
|
|
3636
|
+
const generateParams = params;
|
|
3637
|
+
if (!generateParams?.scope) {
|
|
3638
|
+
if (shouldRespond) {
|
|
3639
|
+
return createErrorResponse(
|
|
3640
|
+
id,
|
|
3641
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3642
|
+
"Missing required parameter: scope"
|
|
3643
|
+
);
|
|
3644
|
+
}
|
|
3645
|
+
return null;
|
|
3646
|
+
}
|
|
3647
|
+
result = await adapter.handleLearnGenerate(id, generateParams);
|
|
3648
|
+
break;
|
|
3649
|
+
}
|
|
3650
|
+
// SDK control methods
|
|
3651
|
+
case RPC_METHODS.SET_PERMISSION_MODE: {
|
|
3652
|
+
const setPermParams = params;
|
|
3653
|
+
if (!setPermParams?.mode) {
|
|
3654
|
+
if (shouldRespond) {
|
|
3655
|
+
return createErrorResponse(
|
|
3656
|
+
id,
|
|
3657
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3658
|
+
"Missing required parameter: mode"
|
|
3659
|
+
);
|
|
3660
|
+
}
|
|
3661
|
+
return null;
|
|
3662
|
+
}
|
|
3663
|
+
result = await adapter.handleSetPermissionMode(setPermParams);
|
|
3664
|
+
break;
|
|
3665
|
+
}
|
|
3666
|
+
case RPC_METHODS.SET_MODEL: {
|
|
3667
|
+
const setModelParams = params;
|
|
3668
|
+
result = await adapter.handleSetModel(setModelParams);
|
|
3669
|
+
break;
|
|
3670
|
+
}
|
|
3671
|
+
case RPC_METHODS.SET_MAX_THINKING_TOKENS: {
|
|
3672
|
+
const setThinkingParams = params;
|
|
3673
|
+
result = await adapter.handleSetMaxThinkingTokens(setThinkingParams);
|
|
3674
|
+
break;
|
|
3675
|
+
}
|
|
3676
|
+
case RPC_METHODS.APPLY_FLAG_SETTINGS: {
|
|
3677
|
+
const applyFlagsParams = params;
|
|
3678
|
+
if (!applyFlagsParams?.settings) {
|
|
3679
|
+
if (shouldRespond) {
|
|
3680
|
+
return createErrorResponse(
|
|
3681
|
+
id,
|
|
3682
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3683
|
+
"Missing required parameter: settings"
|
|
3684
|
+
);
|
|
3685
|
+
}
|
|
3686
|
+
return null;
|
|
3687
|
+
}
|
|
3688
|
+
result = await adapter.handleApplyFlagSettings(applyFlagsParams);
|
|
3689
|
+
break;
|
|
3690
|
+
}
|
|
3691
|
+
case RPC_METHODS.GET_SUPPORTED_MODELS: {
|
|
3692
|
+
result = await adapter.handleGetSupportedModels();
|
|
3693
|
+
break;
|
|
3694
|
+
}
|
|
3695
|
+
case RPC_METHODS.GET_SUPPORTED_COMMANDS: {
|
|
3696
|
+
result = await adapter.handleGetSupportedCommands();
|
|
3697
|
+
break;
|
|
3698
|
+
}
|
|
3699
|
+
case RPC_METHODS.GET_TOOLS_REGISTRY: {
|
|
3700
|
+
result = adapter.handleGetToolsRegistry();
|
|
3701
|
+
break;
|
|
3702
|
+
}
|
|
3703
|
+
case RPC_METHODS.GET_CONTEXT_USAGE: {
|
|
3704
|
+
result = await adapter.handleGetContextUsage();
|
|
3705
|
+
break;
|
|
3706
|
+
}
|
|
3707
|
+
case RPC_METHODS.GOAL_GET: {
|
|
3708
|
+
result = await adapter.handleGoalGet();
|
|
3709
|
+
break;
|
|
3710
|
+
}
|
|
3711
|
+
case RPC_METHODS.GOAL_CREATE: {
|
|
3712
|
+
const goalParams = params;
|
|
3713
|
+
if (!goalParams?.objective) {
|
|
3714
|
+
if (shouldRespond) {
|
|
3715
|
+
return createErrorResponse(id, JSON_RPC_ERROR_CODES.INVALID_PARAMS, "Missing required parameter: objective");
|
|
3716
|
+
}
|
|
3717
|
+
return null;
|
|
3718
|
+
}
|
|
3719
|
+
result = await adapter.handleGoalCreate(goalParams);
|
|
3720
|
+
break;
|
|
3721
|
+
}
|
|
3722
|
+
case RPC_METHODS.GOAL_UPDATE: {
|
|
3723
|
+
result = await adapter.handleGoalUpdate(params ?? {});
|
|
3724
|
+
break;
|
|
3725
|
+
}
|
|
3726
|
+
case RPC_METHODS.GOAL_CLEAR: {
|
|
3727
|
+
result = await adapter.handleGoalClear();
|
|
3728
|
+
break;
|
|
3729
|
+
}
|
|
3730
|
+
case RPC_METHODS.GOAL_QUEUE: {
|
|
3731
|
+
const queueParams = params;
|
|
3732
|
+
if (!queueParams?.objective) {
|
|
3733
|
+
result = await adapter.handleGoalGet();
|
|
3734
|
+
} else {
|
|
3735
|
+
result = await adapter.handleGoalQueue(queueParams);
|
|
3736
|
+
}
|
|
3737
|
+
break;
|
|
3738
|
+
}
|
|
3739
|
+
case RPC_METHODS.GOAL_START_QUEUED: {
|
|
3740
|
+
result = await adapter.handleGoalStartQueued();
|
|
3741
|
+
break;
|
|
3742
|
+
}
|
|
3743
|
+
case RPC_METHODS.GOAL_LIST_TEMPLATES: {
|
|
3744
|
+
result = await adapter.handleGoalListTemplates();
|
|
3745
|
+
break;
|
|
3746
|
+
}
|
|
3747
|
+
case RPC_METHODS.SET_CONTEXT_COMPACT: {
|
|
3748
|
+
const compactParams = params;
|
|
3749
|
+
if (compactParams?.enabled === void 0) {
|
|
3750
|
+
if (shouldRespond) {
|
|
3751
|
+
return {
|
|
3752
|
+
jsonrpc: "2.0",
|
|
3753
|
+
error: { code: -32602, message: "Missing enabled parameter" },
|
|
3754
|
+
id: id ?? null
|
|
3755
|
+
};
|
|
3756
|
+
}
|
|
3757
|
+
return null;
|
|
3758
|
+
}
|
|
3759
|
+
result = await adapter.handleSetContextCompact({ enabled: compactParams.enabled });
|
|
3760
|
+
break;
|
|
3761
|
+
}
|
|
3762
|
+
case RPC_METHODS.RELOAD_PLUGINS: {
|
|
3763
|
+
result = await adapter.handleReloadPlugins();
|
|
3764
|
+
break;
|
|
3765
|
+
}
|
|
3766
|
+
case RPC_METHODS.GET_ACCOUNT_INFO: {
|
|
3767
|
+
result = await adapter.handleGetAccountInfo();
|
|
3768
|
+
break;
|
|
3769
|
+
}
|
|
3770
|
+
case RPC_METHODS.MCP_TOGGLE_SERVER: {
|
|
3771
|
+
const toggleParams = params;
|
|
3772
|
+
if (!toggleParams?.serverName || toggleParams?.enabled === void 0) {
|
|
3773
|
+
if (shouldRespond) {
|
|
3774
|
+
return createErrorResponse(
|
|
3775
|
+
id,
|
|
3776
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3777
|
+
"Missing required parameters: serverName, enabled"
|
|
3778
|
+
);
|
|
3779
|
+
}
|
|
3780
|
+
return null;
|
|
3781
|
+
}
|
|
3782
|
+
result = await adapter.handleMcpToggleServer(toggleParams);
|
|
3783
|
+
break;
|
|
3784
|
+
}
|
|
3785
|
+
case RPC_METHODS.MCP_RECONNECT_SERVER: {
|
|
3786
|
+
const reconnectParams = params;
|
|
3787
|
+
if (!reconnectParams?.serverName) {
|
|
3788
|
+
if (shouldRespond) {
|
|
3789
|
+
return createErrorResponse(
|
|
3790
|
+
id,
|
|
3791
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3792
|
+
"Missing required parameter: serverName"
|
|
3793
|
+
);
|
|
3794
|
+
}
|
|
3795
|
+
return null;
|
|
3796
|
+
}
|
|
3797
|
+
result = await adapter.handleMcpReconnectServer(reconnectParams);
|
|
3798
|
+
break;
|
|
3799
|
+
}
|
|
3800
|
+
case RPC_METHODS.MCP_SET_SERVERS: {
|
|
3801
|
+
const setServersParams = params;
|
|
3802
|
+
if (!setServersParams?.servers) {
|
|
3803
|
+
if (shouldRespond) {
|
|
3804
|
+
return createErrorResponse(
|
|
3805
|
+
id,
|
|
3806
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
3807
|
+
"Missing required parameter: servers"
|
|
3808
|
+
);
|
|
3809
|
+
}
|
|
3810
|
+
return null;
|
|
3811
|
+
}
|
|
3812
|
+
result = await adapter.handleMcpSetServers(setServersParams);
|
|
3813
|
+
break;
|
|
3814
|
+
}
|
|
3815
|
+
default: {
|
|
3816
|
+
if (shouldRespond) {
|
|
3817
|
+
return createErrorResponse(
|
|
3818
|
+
id,
|
|
3819
|
+
JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
3820
|
+
`Method not found: ${method}`
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3823
|
+
return null;
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
if (shouldRespond) {
|
|
3827
|
+
return createResponse(id, result);
|
|
3828
|
+
}
|
|
3829
|
+
return null;
|
|
3830
|
+
} catch (error) {
|
|
3831
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3832
|
+
if (shouldRespond) {
|
|
3833
|
+
return createErrorResponse(
|
|
3834
|
+
id,
|
|
3835
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
3836
|
+
message
|
|
3837
|
+
);
|
|
3838
|
+
}
|
|
3839
|
+
return null;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
export {
|
|
3843
|
+
JSON_RPC_ERROR_CODES,
|
|
3844
|
+
LineReader,
|
|
3845
|
+
MAX_IMAGE_SIZE,
|
|
3846
|
+
RPCAdapter,
|
|
3847
|
+
RPC_METHODS,
|
|
3848
|
+
RPC_NOTIFICATIONS,
|
|
3849
|
+
VALID_IMAGE_MIME_TYPES,
|
|
3850
|
+
createErrorResponse,
|
|
3851
|
+
createNotification,
|
|
3852
|
+
createRequest,
|
|
3853
|
+
createResponse,
|
|
3854
|
+
createTimestamp,
|
|
3855
|
+
generateId,
|
|
3856
|
+
isJsonRpcBatch,
|
|
3857
|
+
isJsonRpcRequest,
|
|
3858
|
+
isJsonRpcResponse,
|
|
3859
|
+
isNotification,
|
|
3860
|
+
isValidImageMimeType,
|
|
3861
|
+
parseRequest,
|
|
3862
|
+
restoreConsole,
|
|
3863
|
+
runRpcMode,
|
|
3864
|
+
serialize,
|
|
3865
|
+
serializeBatch,
|
|
3866
|
+
writeBatchResponse,
|
|
3867
|
+
writeErrorResponse,
|
|
3868
|
+
writeInternalError,
|
|
3869
|
+
writeInvalidRequestError,
|
|
3870
|
+
writeMethodNotFoundError,
|
|
3871
|
+
writeNotification,
|
|
3872
|
+
writeParseError,
|
|
3873
|
+
writeResponse
|
|
3874
|
+
};
|