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.
Files changed (546) hide show
  1. package/README.md +191 -74
  2. package/dist/{AgentRegistry-ODDXPAFR.js → AgentRegistry-GOV7FN2O.js} +2 -2
  3. package/dist/AgentRegistry-J2C6JBZ3.cjs +10 -0
  4. package/dist/{AutomodeManager-EOVHGRPP.js → AutomodeManager-APLLPEYJ.js} +31 -17
  5. package/dist/{AutomodeManager-6ATBE7Q5.cjs → AutomodeManager-MPSXT2RH.cjs} +38 -24
  6. package/dist/CommunitySkillsCache-22BB3J6H.cjs +8 -0
  7. package/dist/{CommunitySkillsCache-QLE57BN5.js → CommunitySkillsCache-ZACDPD4J.js} +2 -2
  8. package/dist/GitHubRegistryFetcher-CYJLF2XL.cjs +7 -0
  9. package/dist/{GitHubRegistryFetcher-NT5GFZXS.js → GitHubRegistryFetcher-J2BWPXJF.js} +1 -1
  10. package/dist/{HookManager-B2F35M27.js → HookManager-2S6AHOC3.js} +1 -1
  11. package/dist/{HookManager-PFAFE3FK.cjs → HookManager-TVEQI5ZU.cjs} +2 -2
  12. package/dist/{ImportWizard-OHRKBANZ.js → ImportWizard-AEBMAKXE.js} +33 -9
  13. package/dist/{ImportWizard-CJRZPPHL.cjs → ImportWizard-AF2XL6DS.cjs} +37 -13
  14. package/dist/LearnAdvisor-KKEQ5QCV.js +9 -0
  15. package/dist/LearnAdvisor-Q7RAYLPF.cjs +9 -0
  16. package/dist/{McpClientManager-NQ3EW2IF.cjs → McpClientManager-BNSKLHIN.cjs} +2 -2
  17. package/dist/{McpClientManager-VBIMGKXU.js → McpClientManager-SL35BR24.js} +1 -1
  18. package/dist/MemoryManager-PMNAEZMB.cjs +8 -0
  19. package/dist/{MemoryManager-2LAT7IHS.js → MemoryManager-QZRLTUB5.js} +2 -2
  20. package/dist/NVIDIAProvider-C3FWQOBZ.cjs +14 -0
  21. package/dist/NVIDIAProvider-SJPY3ONR.js +14 -0
  22. package/dist/{PermissionManager-7NQHRCHY.js → PermissionManager-MT7KBNNR.js} +3 -3
  23. package/dist/PermissionManager-URCNP5EC.cjs +11 -0
  24. package/dist/{ProjectProfiler-UG42W6WD.cjs → ProjectProfiler-CDAE7ECW.cjs} +1 -0
  25. package/dist/{ProjectProfiler-P4QJQWWA.js → ProjectProfiler-NZTJDRHD.js} +1 -0
  26. package/dist/ProviderFactory-56N3ECE4.cjs +12 -0
  27. package/dist/{ProviderFactory-2IYJ5OPW.js → ProviderFactory-RB4RVAF6.js} +4 -1
  28. package/dist/SessionManager-2IZGWASQ.cjs +10 -0
  29. package/dist/{SessionManager-4U4JFQ3C.js → SessionManager-554PHVPC.js} +2 -2
  30. package/dist/SkillsRegistry-GMRVONOQ.cjs +9 -0
  31. package/dist/{SkillsRegistry-RFEINXRT.js → SkillsRegistry-NHHMIUYJ.js} +2 -2
  32. package/dist/SubAgent-4GOR2FIJ.js +13 -0
  33. package/dist/SubAgent-ZJMDH4FI.cjs +13 -0
  34. package/dist/{SyncApiClient-B5RT2ECG.js → SyncApiClient-G3FM65IV.js} +1 -1
  35. package/dist/SyncApiClient-ODBDECOG.cjs +11 -0
  36. package/dist/about-3USFSGOH.js +15 -0
  37. package/dist/about-QR52U5DD.cjs +15 -0
  38. package/dist/acp-5Y2W6OZP.js +1556 -0
  39. package/dist/acp-GSYE75OB.cjs +1556 -0
  40. package/dist/actionExecutor-KHUU3Z3Q.cjs +28 -0
  41. package/dist/actionExecutor-PLQJZLZV.js +28 -0
  42. package/dist/add-dir-BTAD5OZS.cjs +11 -0
  43. package/dist/{add-dir-TUJM3PG5.js → add-dir-HCERJDBR.js} +3 -2
  44. package/dist/agent-B3EVT7NN.cjs +126 -0
  45. package/dist/agent-SATQ3WZ3.js +126 -0
  46. package/dist/agents/builtin/code-cleaner.md +1 -1
  47. package/dist/agents/builtin/docs-writer.md +1 -1
  48. package/dist/agents/builtin/researcher.md +2 -2
  49. package/dist/agents/builtin/reviewer.md +1 -1
  50. package/dist/agents/builtin/tester.md +1 -1
  51. package/dist/agents/builtin/todo-resolver.md +1 -1
  52. package/dist/agents-44CRJGM7.cjs +18 -0
  53. package/dist/agents-NN4ZAJ7R.js +18 -0
  54. package/dist/agents-new-6D6G4QS6.cjs +17 -0
  55. package/dist/agents-new-7GAQ25EK.js +17 -0
  56. package/dist/{autoSkill-LQEVQFIH.js → autoSkill-66PKCYTW.js} +2 -2
  57. package/dist/autoSkill-VQLGBELN.cjs +20 -0
  58. package/dist/automode-45DWV4TN.cjs +10 -0
  59. package/dist/{automode-R6P3VHLS.js → automode-BUF3VGXU.js} +2 -2
  60. package/dist/browserToolBridge-BXRQB4B4.cjs +58 -0
  61. package/dist/browserToolBridge-F5N66PE7.js +58 -0
  62. package/dist/chrome-Q2U73HZB.cjs +50 -0
  63. package/dist/chrome-Q54OALOK.cjs +21 -0
  64. package/dist/chrome-Y3T7EIHG.js +50 -0
  65. package/dist/chrome-ZNJ46OYW.js +21 -0
  66. package/dist/chromeSkill-53TH55PM.js +105 -0
  67. package/dist/chromeSkill-THW7N4IY.cjs +105 -0
  68. package/dist/{chunk-HXGBSJL5.cjs → chunk-22SCR3EV.cjs} +2 -2
  69. package/dist/chunk-26G7YGOW.js +367 -0
  70. package/dist/{chunk-3L53OA4E.cjs → chunk-2ESQR35E.cjs} +10 -10
  71. package/dist/chunk-2H5O745H.js +63 -0
  72. package/dist/{chunk-ULDM2SNB.js → chunk-2IW5YFJ4.js} +48 -47
  73. package/dist/{chunk-U55TWFJI.cjs → chunk-2VHB43IX.cjs} +24 -6
  74. package/dist/chunk-3EDDDZS2.cjs +5 -0
  75. package/dist/{chunk-X5VSP65C.cjs → chunk-3ICORF7M.cjs} +4 -4
  76. package/dist/chunk-3OF56EMA.cjs +197 -0
  77. package/dist/chunk-3UC6DMFI.cjs +93 -0
  78. package/dist/{chunk-64H4FRM3.cjs → chunk-3UHRCHKB.cjs} +32 -34
  79. package/dist/{chunk-JCLYQ2JC.js → chunk-3ZOOH44N.js} +12 -6
  80. package/dist/{chunk-TUD3Z3BD.js → chunk-44ZWOBTI.js} +136 -55
  81. package/dist/chunk-4567QNRB.js +444 -0
  82. package/dist/chunk-45CHNQM6.cjs +517 -0
  83. package/dist/chunk-46MTALKD.js +44 -0
  84. package/dist/{chunk-WHE2SWHU.js → chunk-4E7SHPNQ.js} +2 -2
  85. package/dist/chunk-4LMUDS2K.js +124 -0
  86. package/dist/{chunk-W7RYQJLO.cjs → chunk-4XFHP2SN.cjs} +46 -15
  87. package/dist/chunk-4XVLNOFA.js +360 -0
  88. package/dist/{chunk-GBHDROGL.js → chunk-575PXZX7.js} +16 -4
  89. package/dist/chunk-5A7ZL64N.js +139 -0
  90. package/dist/chunk-5GCQ5UMV.cjs +85 -0
  91. package/dist/chunk-5JTTM5SC.js +59 -0
  92. package/dist/{chunk-IETRBBMP.cjs → chunk-5K3CDSWZ.cjs} +108 -31
  93. package/dist/{chunk-KLWJIPU2.cjs → chunk-5SFV2NCY.cjs} +20 -16
  94. package/dist/chunk-5ZNYX4VH.cjs +71 -0
  95. package/dist/{chunk-A4IJHHV7.cjs → chunk-63ANVAOJ.cjs} +52 -11
  96. package/dist/{chunk-MYISNQH4.js → chunk-65LRPW5W.js} +1 -1
  97. package/dist/chunk-6AYJCDTA.js +360 -0
  98. package/dist/{chunk-X2MSVKDV.js → chunk-6HF6XSCC.js} +2 -2
  99. package/dist/{chunk-AEJH23FO.cjs → chunk-6JWCGQJU.cjs} +6 -6
  100. package/dist/chunk-6OECOAK5.cjs +360 -0
  101. package/dist/chunk-6R25D2H5.js +121 -0
  102. package/dist/chunk-7DJJGKM6.js +77 -0
  103. package/dist/{chunk-VG34MG2U.js → chunk-7IRQ7JEH.js} +9 -6
  104. package/dist/chunk-7MY4JHER.js +27 -0
  105. package/dist/chunk-7PJKTSRN.js +152 -0
  106. package/dist/{chunk-SKYG33B2.cjs → chunk-7PT646AL.cjs} +3 -3
  107. package/dist/chunk-7WAUCLLQ.js +229 -0
  108. package/dist/{chunk-U46VYPLR.cjs → chunk-7XTUL7ZD.cjs} +9 -9
  109. package/dist/chunk-AE2ILW25.cjs +152 -0
  110. package/dist/{chunk-T2M64VHA.cjs → chunk-AOKXYGBQ.cjs} +61 -41
  111. package/dist/chunk-AQ5PVHOC.cjs +113 -0
  112. package/dist/{chunk-N2BLVUPM.cjs → chunk-AZ47LKD5.cjs} +3 -3
  113. package/dist/chunk-B4HSNOIH.cjs +354 -0
  114. package/dist/chunk-B76FJKEJ.cjs +184 -0
  115. package/dist/chunk-BP37FVBM.js +85 -0
  116. package/dist/chunk-BQU3HAE7.js +21 -0
  117. package/dist/chunk-BYE7RQFZ.cjs +121 -0
  118. package/dist/chunk-C46B72VK.js +1034 -0
  119. package/dist/{chunk-HIVRCQS2.js → chunk-C5QIQQ37.js} +56 -25
  120. package/dist/chunk-CCIDL4SA.js +19931 -0
  121. package/dist/{chunk-XVUHNWMX.js → chunk-CECH6QQP.js} +17 -19
  122. package/dist/chunk-CFAWTLSC.js +13 -0
  123. package/dist/{chunk-ZYQMLKOK.cjs → chunk-CK4HAHVY.cjs} +212 -70
  124. package/dist/chunk-CO2AADYU.cjs +360 -0
  125. package/dist/chunk-CRTCZ4WL.cjs +19931 -0
  126. package/dist/chunk-CSTUTDTH.js +75 -0
  127. package/dist/{chunk-K2C56QGS.cjs → chunk-D546G7DA.cjs} +1650 -479
  128. package/dist/{chunk-CNBKZEX5.cjs → chunk-DA7NBAJK.cjs} +49 -17
  129. package/dist/{chunk-G4CAKI3V.js → chunk-DGBPWODD.js} +7 -2
  130. package/dist/chunk-DHUQZ53B.cjs +29 -0
  131. package/dist/{chunk-RGR6ME5J.cjs → chunk-DI57A4BX.cjs} +25 -28
  132. package/dist/{chunk-5K6NGAVM.js → chunk-DNSD7DVJ.js} +67 -52
  133. package/dist/{chunk-RDF37HKB.cjs → chunk-DSSCERHI.cjs} +3 -2
  134. package/dist/{chunk-NAJ4IZKD.cjs → chunk-EA2MS25U.cjs} +8 -6
  135. package/dist/{chunk-SJAVBCOA.js → chunk-EEHWALXA.js} +94 -3
  136. package/dist/chunk-ES2HJQ4N.js +37 -0
  137. package/dist/{chunk-G27PQQFD.js → chunk-EYHKL4QC.js} +1 -1
  138. package/dist/{chunk-SV2WA57F.js → chunk-FBQJZKFX.js} +38 -15
  139. package/dist/chunk-FFBDRUO5.cjs +59 -0
  140. package/dist/{chunk-N7LI55V4.js → chunk-FFHSCM5M.js} +15 -8
  141. package/dist/{chunk-SAHBLB3E.js → chunk-FP46B4X3.js} +208 -3
  142. package/dist/chunk-FQVG6ZHF.js +197 -0
  143. package/dist/{chunk-J2GSFVUV.cjs → chunk-GAOPJ5S3.cjs} +74 -59
  144. package/dist/{chunk-S52YW5ZQ.js → chunk-GNBBIAMD.js} +16 -19
  145. package/dist/chunk-GSDV75A5.js +715 -0
  146. package/dist/chunk-GWY26SUD.cjs +63 -0
  147. package/dist/{chunk-TUAITHWL.js → chunk-H426KOGY.js} +2 -1
  148. package/dist/{chunk-EZMINVLU.js → chunk-H4D2Q2AL.js} +5 -2
  149. package/dist/chunk-HC2Q6A3E.cjs +4967 -0
  150. package/dist/{chunk-3WVJEL7K.cjs → chunk-HDK2EHVH.cjs} +3 -1
  151. package/dist/{chunk-5IXII4HX.cjs → chunk-HG3ZASBH.cjs} +23 -16
  152. package/dist/chunk-HK5A54AV.cjs +280 -0
  153. package/dist/{chunk-LQGVEP3E.js → chunk-HQUSEWT4.js} +45 -13
  154. package/dist/chunk-HSWWM6AM.js +2340 -0
  155. package/dist/chunk-HTU4W3GB.js +183 -0
  156. package/dist/{chunk-HLHTG5ZU.cjs → chunk-HVCIB4SW.cjs} +14 -12
  157. package/dist/chunk-HXHE2KAO.js +385 -0
  158. package/dist/{chunk-LJFUXC56.cjs → chunk-HXQREVTA.cjs} +9 -6
  159. package/dist/{chunk-SLQAYV3W.js → chunk-HZWU6IO3.js} +11 -2
  160. package/dist/chunk-I2ZK3AOD.js +866 -0
  161. package/dist/chunk-IEPLQ47J.js +719 -0
  162. package/dist/chunk-J5HE6CUM.cjs +124 -0
  163. package/dist/{chunk-LIEXWM2M.js → chunk-JAQO6XDB.js} +19 -1
  164. package/dist/chunk-JB3JCYBJ.js +113 -0
  165. package/dist/chunk-JCUHCH37.cjs +247 -0
  166. package/dist/{chunk-FPHU2ES6.cjs → chunk-JM3ZTQUK.cjs} +19 -9
  167. package/dist/{chunk-NDMIPTV4.js → chunk-JMJRFSNJ.js} +8 -3
  168. package/dist/{chunk-ZLSGXMGQ.js → chunk-JMN3GZU6.js} +2 -0
  169. package/dist/chunk-JPFRI4L4.js +4967 -0
  170. package/dist/{chunk-BVKXEQVG.cjs → chunk-JV5HVCHU.cjs} +22 -10
  171. package/dist/chunk-KA2U6MY2.js +388 -0
  172. package/dist/{chunk-SEKD5FH3.cjs → chunk-KASXKDF2.cjs} +8 -3
  173. package/dist/chunk-KJ26T7GM.cjs +367 -0
  174. package/dist/chunk-KM7R5YPS.cjs +385 -0
  175. package/dist/{chunk-MBBY4ZIK.js → chunk-KMP6Y3LJ.js} +4 -1
  176. package/dist/chunk-KWXGDSYT.js +184 -0
  177. package/dist/{chunk-C5IJIM2V.cjs → chunk-L46OUKW5.cjs} +68 -37
  178. package/dist/{chunk-6UJMCWRY.js → chunk-L6OH44HL.js} +19 -9
  179. package/dist/chunk-LANGD5CO.js +280 -0
  180. package/dist/{chunk-APIXPPMT.js → chunk-LEZEWKPA.js} +1004 -39
  181. package/dist/{chunk-ULQ6MDSJ.cjs → chunk-LFDPTJYF.cjs} +43 -35
  182. package/dist/chunk-LJD7KR3L.cjs +44 -0
  183. package/dist/{chunk-NCC6ETZS.js → chunk-LUMV3DB2.js} +41 -33
  184. package/dist/{chunk-QXH5RCFI.js → chunk-M5DK524Z.js} +2 -2
  185. package/dist/chunk-M7B7RRBK.cjs +1034 -0
  186. package/dist/chunk-MANJ67D3.js +3897 -0
  187. package/dist/{chunk-HPHJ73GU.cjs → chunk-MGNXABSU.cjs} +9 -9
  188. package/dist/{chunk-6ZCULLCA.js → chunk-MMKZSJUN.js} +1 -1
  189. package/dist/{chunk-DVUHHH3B.cjs → chunk-MQQH4XQH.cjs} +4 -4
  190. package/dist/chunk-MUNUUFU7.cjs +21 -0
  191. package/dist/{chunk-DVZOENQ7.cjs → chunk-MZN6JBRZ.cjs} +9 -4
  192. package/dist/{chunk-OOKY3HPZ.js → chunk-NB6M6ESM.js} +50 -9
  193. package/dist/{chunk-BYONM7UM.js → chunk-NBGOIFKP.js} +265 -18
  194. package/dist/chunk-NHWHEW7M.cjs +75 -0
  195. package/dist/chunk-NQZH5CR2.cjs +468 -0
  196. package/dist/{chunk-EGPXJERY.cjs → chunk-NV6LCD2I.cjs} +119 -28
  197. package/dist/chunk-NVATU4V6.cjs +44 -0
  198. package/dist/{chunk-YZXUDM5X.js → chunk-NZ3ZWLUW.js} +204 -62
  199. package/dist/chunk-NZ7GCK7Y.cjs +92 -0
  200. package/dist/{chunk-VEKDGU2Q.cjs → chunk-NZQFKXM3.cjs} +49 -25
  201. package/dist/chunk-O5GI6SR3.js +59 -0
  202. package/dist/{chunk-56SWIDEL.cjs → chunk-OCATAKXV.cjs} +57 -56
  203. package/dist/{chunk-SKV2F3NM.js → chunk-OIGYWOL6.js} +1 -1
  204. package/dist/{chunk-IFFXSTOM.cjs → chunk-ONVYXTUT.cjs} +3 -3
  205. package/dist/chunk-OR67YXQK.cjs +13 -0
  206. package/dist/chunk-OV3T5MUH.cjs +715 -0
  207. package/dist/{chunk-OHUZKDGX.js → chunk-P4FUTSVK.js} +3 -3
  208. package/dist/chunk-P6SLT2F4.cjs +139 -0
  209. package/dist/{chunk-TNZRZQ7Q.js → chunk-PB7W7R72.js} +3 -78
  210. package/dist/chunk-PCM3N3CL.cjs +37 -0
  211. package/dist/{chunk-2AA5MFES.js → chunk-PGFLPURU.js} +8 -5
  212. package/dist/{chunk-DJDE4DTT.cjs → chunk-PIXQ2AVM.cjs} +25 -19
  213. package/dist/chunk-PNIAIOMZ.cjs +229 -0
  214. package/dist/{chunk-HTLINWX6.cjs → chunk-PQBYFEBL.cjs} +16 -13
  215. package/dist/{chunk-22D2CNTP.cjs → chunk-PSAH4ZQB.cjs} +5 -2
  216. package/dist/{chunk-3VTAFAL2.js → chunk-PTTZI4QZ.js} +16 -12
  217. package/dist/{chunk-WPVWQSL7.cjs → chunk-PY73W5MQ.cjs} +16 -13
  218. package/dist/{chunk-EGMZDTSL.js → chunk-PZZMIYII.js} +10 -2
  219. package/dist/{chunk-HBZU3RBZ.js → chunk-Q3BS6FPM.js} +34 -10
  220. package/dist/chunk-QBYGMMDD.js +517 -0
  221. package/dist/chunk-QLZOMZO5.cjs +388 -0
  222. package/dist/{chunk-ADUFCS4Q.cjs → chunk-QQ64HEHP.cjs} +160 -79
  223. package/dist/{chunk-L3TWPROA.js → chunk-QRQF3556.js} +44 -24
  224. package/dist/{chunk-YHD6TUIR.cjs → chunk-QW2RW2GY.cjs} +2 -0
  225. package/dist/chunk-RAKO7UN7.js +114 -0
  226. package/dist/{chunk-7TQH3CL4.cjs → chunk-RBXBH6EB.cjs} +78 -35
  227. package/dist/chunk-RFUKZIJF.cjs +78 -0
  228. package/dist/chunk-RS2E32YB.js +71 -0
  229. package/dist/{chunk-OLSBBZW6.cjs → chunk-S5JNQIGL.cjs} +5 -5
  230. package/dist/{chunk-FTYY5JJD.js → chunk-S5QKRA2V.js} +2 -2
  231. package/dist/chunk-SD3NTC7D.cjs +77 -0
  232. package/dist/{chunk-KPELYZ6L.js → chunk-SDLY4X3G.js} +2 -2
  233. package/dist/{chunk-IDFF5J2E.js → chunk-SFFEKZGC.js} +38 -7
  234. package/dist/{chunk-EGFT4PGW.js → chunk-SHRLFX6F.js} +8 -3
  235. package/dist/{chunk-3WICOC33.js → chunk-SNDDZG5H.js} +124 -84
  236. package/dist/{chunk-CZXGCVTR.cjs → chunk-SOVR7S3T.cjs} +2 -2
  237. package/dist/chunk-SPQ7QIQ6.js +78 -0
  238. package/dist/{chunk-XRZEUWKF.js → chunk-SRMGWMQO.js} +1 -1
  239. package/dist/{chunk-R33VKSH5.cjs → chunk-SVVP4UUZ.cjs} +11 -11
  240. package/dist/{chunk-7BTSG4ME.cjs → chunk-SY2P3Z5W.cjs} +1004 -39
  241. package/dist/chunk-SZD45IDG.js +468 -0
  242. package/dist/{chunk-3O3MOK5C.cjs → chunk-TE4SYTWR.cjs} +1114 -142
  243. package/dist/chunk-TH26BQJG.js +101 -0
  244. package/dist/{chunk-QNGEW5TC.js → chunk-TR6NECEZ.js} +1 -1
  245. package/dist/{chunk-YGN4CQIP.js → chunk-TYBPTKFT.js} +1 -1
  246. package/dist/{chunk-GJH7XMSK.js → chunk-U2QUMKCB.js} +8 -6
  247. package/dist/{chunk-47CKWKEX.cjs → chunk-U6PLSPMD.cjs} +9 -4
  248. package/dist/chunk-UOQECODR.js +34 -0
  249. package/dist/chunk-UR27UDTB.js +354 -0
  250. package/dist/chunk-UWZ4G3SQ.js +93 -0
  251. package/dist/{chunk-Y72HH2TF.cjs → chunk-V3SZLWEQ.cjs} +33 -24
  252. package/dist/chunk-V4HGZSKQ.cjs +183 -0
  253. package/dist/{chunk-3PDTTAKJ.js → chunk-V5ELP2XE.js} +19 -12
  254. package/dist/{chunk-3K2ESU53.cjs → chunk-VKOXFT4L.cjs} +2 -2
  255. package/dist/{chunk-XTB6VJVQ.cjs → chunk-VLGGMQUN.cjs} +6 -6
  256. package/dist/chunk-VQHSYAPZ.cjs +3897 -0
  257. package/dist/chunk-VUGOOGHB.js +400 -0
  258. package/dist/chunk-W5QLA6WP.cjs +866 -0
  259. package/dist/chunk-WBU4Q4GS.cjs +400 -0
  260. package/dist/{chunk-KWXVKLQ5.cjs → chunk-WGNMOVMT.cjs} +7 -82
  261. package/dist/chunk-WJYFLQ7G.cjs +27 -0
  262. package/dist/{chunk-RKJTGGMU.cjs → chunk-WKRDBCP2.cjs} +221 -16
  263. package/dist/{chunk-ZSPXQYG2.js → chunk-WNJXIACY.js} +7 -5
  264. package/dist/{chunk-AYS2ASM7.js → chunk-WPE2XHVX.js} +1 -1
  265. package/dist/chunk-WTB7AFL6.cjs +101 -0
  266. package/dist/{chunk-JYTDYJVW.js → chunk-X3TI5TJJ.js} +1 -1
  267. package/dist/chunk-X5P6QQOB.cjs +719 -0
  268. package/dist/{chunk-245KJE5Y.cjs → chunk-X7XMITIL.cjs} +14 -6
  269. package/dist/chunk-XF2WIKHR.cjs +34 -0
  270. package/dist/{chunk-DV2ZHK7B.cjs → chunk-XNIMSVS6.cjs} +49 -26
  271. package/dist/chunk-XW3XCK4E.cjs +59 -0
  272. package/dist/{chunk-N23UAW4I.js → chunk-XZVDYC5U.js} +7 -2
  273. package/dist/chunk-Y5BDE24P.cjs +444 -0
  274. package/dist/{chunk-NAGQ2PDC.js → chunk-YC5OBZQU.js} +1604 -433
  275. package/dist/chunk-YISPVAXO.cjs +2340 -0
  276. package/dist/{chunk-KQGPTCQJ.js → chunk-YQDI753V.js} +68 -25
  277. package/dist/{chunk-UJ2JSM6H.js → chunk-YVQI26H4.js} +2 -0
  278. package/dist/{chunk-NNPAM4HC.cjs → chunk-YWH55BWK.cjs} +15 -6
  279. package/dist/{chunk-X2YOZQIP.cjs → chunk-YWTIXHU6.cjs} +266 -19
  280. package/dist/{chunk-XX2ZO7DS.js → chunk-YXM6SA7P.js} +25 -16
  281. package/dist/chunk-YZWE7XSM.js +5 -0
  282. package/dist/chunk-ZASDSY7P.cjs +114 -0
  283. package/dist/{chunk-2UC22DJU.js → chunk-ZNGRLCFQ.js} +30 -4
  284. package/dist/{chunk-KANW6OYC.cjs → chunk-ZNYZB7XY.cjs} +34 -8
  285. package/dist/{chunk-NA6WQDYW.js → chunk-ZPLCAXJW.js} +1088 -116
  286. package/dist/{chunk-7UOUW76C.js → chunk-ZQAT5VT5.js} +101 -24
  287. package/dist/chunk-ZUYYHKQA.js +44 -0
  288. package/dist/clear-QJXU25IF.cjs +12 -0
  289. package/dist/{clear-A3N4GK2S.js → clear-Y5TO3RZA.js} +3 -3
  290. package/dist/communityInstaller-LXMVKVAV.cjs +22 -0
  291. package/dist/{communityInstaller-LOP2EDH5.js → communityInstaller-RVL4STPS.js} +8 -5
  292. package/dist/completion-JX4T2ONW.cjs +17 -0
  293. package/dist/completion-SE3XYG74.js +17 -0
  294. package/dist/config-3224PRW4.cjs +21 -0
  295. package/dist/{config-HPJPKTO6.js → config-7KPHKFTP.js} +7 -4
  296. package/dist/{constants-LISJW3DD.js → constants-EJFAWJQI.js} +1 -1
  297. package/dist/constants-MCCGUU5F.cjs +21 -0
  298. package/dist/{defaultHooks-IHSJR2AX.cjs → defaultHooks-2V2CQL63.cjs} +25 -10
  299. package/dist/{defaultHooks-KUKHK3AG.js → defaultHooks-TMHDU3FS.js} +25 -10
  300. package/dist/export-BJVIDZC4.js +15 -0
  301. package/dist/export-KU4557HK.cjs +15 -0
  302. package/dist/feature-K3LG5IJP.cjs +14 -0
  303. package/dist/feature-V4JF5TNJ.js +14 -0
  304. package/dist/features-5OJTLKS7.js +23 -0
  305. package/dist/features-VCBJQXCX.cjs +23 -0
  306. package/dist/feedback-D4437VE4.js +18 -0
  307. package/dist/feedback-VZPEHGFY.cjs +18 -0
  308. package/dist/fffSearchProvider-2YCNKOYD.js +412 -0
  309. package/dist/fffSearchProvider-W6627E2V.cjs +412 -0
  310. package/dist/{filesystem-Z7BWAWMZ.js → filesystem-L6DQKGWK.js} +3 -2
  311. package/dist/filesystem-PGUPCMVK.cjs +11 -0
  312. package/dist/go-X4E6BCD6.js +12 -0
  313. package/dist/go-XREVFS5I.cjs +12 -0
  314. package/dist/goal-4M3J6JS2.cjs +16 -0
  315. package/dist/goal-EI66BV7W.js +16 -0
  316. package/dist/help-GGFS7WHY.cjs +12 -0
  317. package/dist/{help-GFQXNZOK.js → help-MLIROWKM.js} +2 -2
  318. package/dist/{history-E3N6BJP7.js → history-GQJ6RZD6.js} +2 -2
  319. package/dist/history-J4LUIOSI.cjs +14 -0
  320. package/dist/hooks-FSRIUS6A.cjs +18 -0
  321. package/dist/hooks-PPFHCF7T.js +18 -0
  322. package/dist/i18n-CI6VFXL5.cjs +33 -0
  323. package/dist/{i18n-SY7QRM22.js → i18n-Q7UZJRPL.js} +1 -1
  324. package/dist/ide-BUSVE54P.js +15 -0
  325. package/dist/ide-YR27BPGM.cjs +15 -0
  326. package/dist/immediateCommandRouter-MTEHZXQX.js +15 -0
  327. package/dist/immediateCommandRouter-ROXU3MWT.cjs +15 -0
  328. package/dist/{import-W7SVLSTC.js → import-3VBKI6BN.js} +3 -3
  329. package/dist/{import-ADI37ZUR.cjs → import-C7S6UJMW.cjs} +3 -3
  330. package/dist/import-DBK4OCDF.cjs +10 -0
  331. package/dist/{import-KGKKZ3B7.js → import-U47DXCA7.js} +2 -2
  332. package/dist/index.cjs +837 -23011
  333. package/dist/index.d.cts +95 -0
  334. package/dist/index.d.ts +95 -0
  335. package/dist/index.js +864 -23038
  336. package/dist/init-OXTYS72D.cjs +10 -0
  337. package/dist/{init-7MFK626E.js → init-Q2O4R42R.js} +2 -2
  338. package/dist/inkMode-VUE6ZDLD.cjs +7 -0
  339. package/dist/inkMode-WBNFOSAT.js +7 -0
  340. package/dist/inputPrompt-3CFZDUBH.js +90 -0
  341. package/dist/inputPrompt-JMACL4EB.cjs +90 -0
  342. package/dist/language-EK3M6UBV.cjs +22 -0
  343. package/dist/language-Q3RUGGOW.js +22 -0
  344. package/dist/learn-3DSX7DYG.cjs +23 -0
  345. package/dist/learn-OPOH5L43.js +23 -0
  346. package/dist/login-GST7MWXJ.cjs +27 -0
  347. package/dist/login-Q7DZKAX4.js +27 -0
  348. package/dist/logout-2G7OUK7I.cjs +24 -0
  349. package/dist/logout-FNBBL2UI.js +24 -0
  350. package/dist/mcp-AH3MMUBU.js +21 -0
  351. package/dist/mcp-DW7R63IB.cjs +21 -0
  352. package/dist/{mcp-install-2FEROZTL.js → mcp-install-222PCKSW.js} +18 -10
  353. package/dist/{mcp-install-WM6BQRI5.cjs → mcp-install-IA4ZS2SV.cjs} +22 -14
  354. package/dist/memory-6NX3DAIY.cjs +10 -0
  355. package/dist/{memory-J73WZH2I.js → memory-VB46T5H3.js} +2 -2
  356. package/dist/model-64NAELFS.cjs +10 -0
  357. package/dist/{model-AES267IN.js → model-SJJG64AM.js} +2 -2
  358. package/dist/new-DU5SOOOY.cjs +12 -0
  359. package/dist/{new-5CLF3MKH.js → new-ERZ5C6CN.js} +3 -3
  360. package/dist/onboarding-2U2BV2KE.cjs +36 -0
  361. package/dist/onboarding-ZQXMPSMJ.js +36 -0
  362. package/dist/permissions-7ACNFK7A.js +10 -0
  363. package/dist/permissions-GSNNV7RJ.cjs +10 -0
  364. package/dist/plan-XEJMOT55.cjs +13 -0
  365. package/dist/{plan-65HMS5HQ.js → plan-YYUAXPTL.js} +3 -1
  366. package/dist/pr-review-CW6J7P62.cjs +9 -0
  367. package/dist/pr-review-YZSBQVT2.js +9 -0
  368. package/dist/{quit-XDZYRSPU.js → quit-WY6T267G.js} +2 -2
  369. package/dist/quit-XIRE2KRE.cjs +10 -0
  370. package/dist/rawMode-6W5AXAKI.cjs +7 -0
  371. package/dist/rawMode-GFNLXQPU.js +7 -0
  372. package/dist/{registry-PTHWERKC.js → registry-4DXUDKJN.js} +29 -44
  373. package/dist/{registry-IVT4G2RT.cjs → registry-UEO3ETZ7.cjs} +65 -80
  374. package/dist/repeat-P4FAPE3Y.cjs +17 -0
  375. package/dist/{repeat-EVCWUL6Z.js → repeat-RALE6AUO.js} +7 -3
  376. package/dist/resume-RQZ3WXBP.cjs +17 -0
  377. package/dist/resume-XSXZMDMD.js +17 -0
  378. package/dist/review-QHP2KP4Q.js +9 -0
  379. package/dist/review-UWHWQHCB.cjs +9 -0
  380. package/dist/ripgrep-67SCU2BA.cjs +9 -0
  381. package/dist/ripgrep-VHJQQ55W.js +9 -0
  382. package/dist/rpc-XH7QLN4H.js +3874 -0
  383. package/dist/rpc-YF54T7JU.cjs +3874 -0
  384. package/dist/search-VXXFGZWU.cjs +21 -0
  385. package/dist/search-YAWGX7P7.js +21 -0
  386. package/dist/{sessions-6GWEBMKS.js → sessions-NJYHJOEL.js} +2 -2
  387. package/dist/sessions-OSG3UJEZ.cjs +10 -0
  388. package/dist/settings-SO2UIGWV.cjs +42 -0
  389. package/dist/settings-ZXUQH3DO.js +42 -0
  390. package/dist/setup-KG7EGKF5.js +30 -0
  391. package/dist/setup-RSOPCQ57.cjs +30 -0
  392. package/dist/share-WFAGZ5PY.js +17 -0
  393. package/dist/share-ZU3SGACF.cjs +17 -0
  394. package/dist/skills-KBVAQAD2.cjs +29 -0
  395. package/dist/skills-NBTNDVAY.js +29 -0
  396. package/dist/{skills-ZZCIAS7C.js → skills-OB6RDW7D.js} +10 -7
  397. package/dist/{skills-PG542VEB.cjs → skills-ZROBG3RZ.cjs} +13 -10
  398. package/dist/{skills-install-SRC3Z2MS.js → skills-install-BHTIEMKH.js} +21 -70
  399. package/dist/{skills-install-67DOBPJC.cjs → skills-install-ILX6QVEF.cjs} +34 -83
  400. package/dist/skills-new-B45VQ2PP.cjs +18 -0
  401. package/dist/skills-new-YMRP2HNO.js +18 -0
  402. package/dist/slashCommands-53VYIBJU.js +105 -0
  403. package/dist/slashCommands-BG2RGGZ6.cjs +105 -0
  404. package/dist/status-CQ2IUOVK.cjs +24 -0
  405. package/dist/status-E7IGNVPC.js +24 -0
  406. package/dist/summarizer-DGPHE5IQ.js +17 -0
  407. package/dist/summarizer-JNXLUAQG.cjs +17 -0
  408. package/dist/sync-7C25MOT2.js +22 -0
  409. package/dist/{sync-VU2NSJ4O.js → sync-OCJN4ZSO.js} +3 -3
  410. package/dist/sync-XRP46IVG.cjs +40 -0
  411. package/dist/sync-ZMFVE7T4.cjs +22 -0
  412. package/dist/{teammate-SXRVXNQV.cjs → teammate-D77B6QRT.cjs} +31 -9
  413. package/dist/{teammate-SD26GR37.js → teammate-EZCMHOIL.js} +30 -8
  414. package/dist/templates-ARG2VRWW.cjs +11 -0
  415. package/dist/templates-UGVZV3KJ.js +11 -0
  416. package/dist/theme-KKRDE6P7.cjs +22 -0
  417. package/dist/theme-XF7XIWBQ.js +22 -0
  418. package/dist/tools-3PPTTKFV.js +9 -0
  419. package/dist/tools-THIQA7WC.cjs +9 -0
  420. package/dist/ui/questionModal.cjs +8 -5
  421. package/dist/ui/questionModal.js +7 -4
  422. package/dist/{undo-OL2EDBRY.js → undo-GNUTFXCW.js} +2 -2
  423. package/dist/undo-U4KN7QQM.cjs +10 -0
  424. package/dist/usage-QSTNSDAO.js +24 -0
  425. package/dist/usage-YDEMQBNQ.cjs +24 -0
  426. package/dist/web-3BA2WV37.cjs +37 -0
  427. package/dist/web-6FYGBX5K.js +37 -0
  428. package/dist/workspaceSafety-MDJGHK6D.cjs +9 -0
  429. package/dist/workspaceSafety-XOUMUBVB.js +9 -0
  430. package/dist/yolo-GF2YD7ZI.js +9 -0
  431. package/dist/yolo-OGDA7HNC.cjs +9 -0
  432. package/dist/yoloMode-3DJDA75U.cjs +17 -0
  433. package/dist/yoloMode-4JOOSU26.js +17 -0
  434. package/package.json +51 -49
  435. package/dist/AgentRegistry-HRPN6ZOF.cjs +0 -10
  436. package/dist/CommunitySkillsCache-KE435RAR.cjs +0 -8
  437. package/dist/GitHubRegistryFetcher-I45SESIL.cjs +0 -7
  438. package/dist/LearnAdvisor-FLBA6FDD.js +0 -9
  439. package/dist/LearnAdvisor-GG3CXQF3.cjs +0 -9
  440. package/dist/MemoryManager-2LQPIYVE.cjs +0 -8
  441. package/dist/PermissionManager-X57BXHJ6.cjs +0 -11
  442. package/dist/ProviderFactory-KPJOGQWF.cjs +0 -9
  443. package/dist/SessionManager-YBJAZXNO.cjs +0 -10
  444. package/dist/SkillsRegistry-7O72A6TZ.cjs +0 -9
  445. package/dist/SubAgent-JT4HZHN7.js +0 -11
  446. package/dist/SubAgent-VPNYDWAU.cjs +0 -11
  447. package/dist/SyncApiClient-HQXJL5BT.cjs +0 -11
  448. package/dist/about-4DB5KTHW.js +0 -12
  449. package/dist/about-LXAOXZFT.cjs +0 -12
  450. package/dist/actionExecutor-23JB2WUC.js +0 -19
  451. package/dist/actionExecutor-X5UEZSKH.cjs +0 -19
  452. package/dist/add-dir-YC37DMSF.cjs +0 -10
  453. package/dist/agents-YF3BSUU5.js +0 -12
  454. package/dist/agents-ZOUHPMYR.cjs +0 -12
  455. package/dist/agents-new-HSH4GQPG.js +0 -14
  456. package/dist/agents-new-VYUDOCE7.cjs +0 -14
  457. package/dist/autoSkill-X5W52WOE.cjs +0 -20
  458. package/dist/automode-SJGM7VEI.cjs +0 -10
  459. package/dist/chunk-ALYU6VTM.js +0 -105
  460. package/dist/chunk-B53A2NM2.js +0 -2030
  461. package/dist/chunk-BJXSNT46.js +0 -100
  462. package/dist/chunk-CB4E2T5N.cjs +0 -312
  463. package/dist/chunk-DNUOXBHL.js +0 -539
  464. package/dist/chunk-EFX2QSZX.cjs +0 -33
  465. package/dist/chunk-GCXYXLRA.cjs +0 -111
  466. package/dist/chunk-H2ZRHQQV.js +0 -33
  467. package/dist/chunk-HNRPK5MY.cjs +0 -85
  468. package/dist/chunk-HVKOZ2VP.cjs +0 -115
  469. package/dist/chunk-JJLYWH5Y.cjs +0 -100
  470. package/dist/chunk-LWUJFGOZ.js +0 -115
  471. package/dist/chunk-MERYP6AM.cjs +0 -539
  472. package/dist/chunk-MZAPWNAC.cjs +0 -207
  473. package/dist/chunk-NTSDP2WB.js +0 -226
  474. package/dist/chunk-OUZQXMHL.cjs +0 -226
  475. package/dist/chunk-PGESAU2W.cjs +0 -2030
  476. package/dist/chunk-SYVYLZZF.cjs +0 -24
  477. package/dist/chunk-SZOLA6FR.js +0 -111
  478. package/dist/chunk-VWDHR4HV.js +0 -168
  479. package/dist/chunk-Y45G6ZO5.cjs +0 -168
  480. package/dist/chunk-YRLYSQEQ.cjs +0 -105
  481. package/dist/chunk-ZYVS43MU.js +0 -312
  482. package/dist/clear-GK4IEUUS.cjs +0 -12
  483. package/dist/communityInstaller-XXC7RLE4.cjs +0 -19
  484. package/dist/completion-HWABSAEL.js +0 -14
  485. package/dist/completion-IUUVQG4D.cjs +0 -14
  486. package/dist/config-HF7WOLZF.cjs +0 -18
  487. package/dist/constants-PEO3P2SJ.cjs +0 -21
  488. package/dist/export-QJAV2FCZ.js +0 -12
  489. package/dist/export-XSRFXGWU.cjs +0 -12
  490. package/dist/feedback-4TCIL3ML.cjs +0 -15
  491. package/dist/feedback-SJ6VVEY3.js +0 -15
  492. package/dist/filesystem-W56QZUJF.cjs +0 -10
  493. package/dist/help-ISBVQL3S.cjs +0 -12
  494. package/dist/history-XQ4GTSFU.cjs +0 -14
  495. package/dist/hooks-CJNKJ5PF.js +0 -13
  496. package/dist/hooks-UTMBTAXT.cjs +0 -13
  497. package/dist/i18n-N7QQ7A5M.cjs +0 -33
  498. package/dist/ide-RTA4UJV4.js +0 -12
  499. package/dist/ide-VWVOLIFF.cjs +0 -12
  500. package/dist/immediateCommandRouter-BW34JNXL.js +0 -9
  501. package/dist/immediateCommandRouter-SHOVNB5X.cjs +0 -9
  502. package/dist/import-ZLJVONXH.cjs +0 -10
  503. package/dist/init-TBKAB4LZ.cjs +0 -10
  504. package/dist/language-MDSHEXHB.cjs +0 -18
  505. package/dist/language-PXTQSHIG.js +0 -18
  506. package/dist/learn-623TW5EK.cjs +0 -20
  507. package/dist/learn-BCPV7GM2.js +0 -20
  508. package/dist/localProjectPermissions-BHQXEWZJ.cjs +0 -18
  509. package/dist/localProjectPermissions-GMOUYQM6.js +0 -18
  510. package/dist/login-QMVEETWJ.js +0 -20
  511. package/dist/login-QYMXAL3K.cjs +0 -20
  512. package/dist/logout-2CMTDAOJ.js +0 -18
  513. package/dist/logout-ZOHVZAUK.cjs +0 -18
  514. package/dist/mcp-IUVKK65S.js +0 -18
  515. package/dist/mcp-TXC7PYG3.cjs +0 -18
  516. package/dist/memory-WRIHDEPK.cjs +0 -10
  517. package/dist/model-RLP75SF5.cjs +0 -10
  518. package/dist/new-HLSFL6A4.cjs +0 -12
  519. package/dist/permissions-GP6FTGZ2.js +0 -13
  520. package/dist/permissions-O6EKKPOG.cjs +0 -13
  521. package/dist/plan-MCAXDIM2.cjs +0 -11
  522. package/dist/quit-TQX6GXA5.cjs +0 -10
  523. package/dist/repeat-BSPS5TWD.cjs +0 -13
  524. package/dist/resume-2GOPDLL4.cjs +0 -13
  525. package/dist/resume-37IUVDA6.js +0 -13
  526. package/dist/search-7KUSHIBL.cjs +0 -17
  527. package/dist/search-OJGDRIMA.js +0 -17
  528. package/dist/sessions-CYYCHSQG.cjs +0 -10
  529. package/dist/settings-2D7CAO66.cjs +0 -30
  530. package/dist/settings-BXR6SBJP.js +0 -30
  531. package/dist/share-BXQY5IQU.js +0 -14
  532. package/dist/share-OSFXZBGS.cjs +0 -14
  533. package/dist/skills-FL6O6AOM.cjs +0 -26
  534. package/dist/skills-PNKQZRNK.js +0 -26
  535. package/dist/skills-new-XFMEHHIF.cjs +0 -15
  536. package/dist/skills-new-ZNZPHUKS.js +0 -15
  537. package/dist/slashCommands-LLCNPK3X.js +0 -76
  538. package/dist/slashCommands-RXZZS6RE.cjs +0 -76
  539. package/dist/status-BCECUJXT.cjs +0 -11
  540. package/dist/status-EFO7MQU3.js +0 -11
  541. package/dist/sync-IJYJ6KKM.js +0 -18
  542. package/dist/sync-LFT6SBPF.cjs +0 -18
  543. package/dist/sync-U7SDPBNZ.cjs +0 -40
  544. package/dist/theme-AWBHSG7J.cjs +0 -18
  545. package/dist/theme-TQLBPJ2E.js +0 -18
  546. package/dist/undo-IBBGP7A2.cjs +0 -10
@@ -1,2030 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/providers/errors.ts
2
- var ApiError = class extends Error {
3
- constructor(message, code, httpStatus, retryable, retryAfterMs, rawDetail) {
4
- super(message);
5
- this.name = "ApiError";
6
- this.code = code;
7
- this.httpStatus = httpStatus;
8
- this.retryable = retryable;
9
- this.retryAfterMs = retryAfterMs;
10
- this.rawDetail = rawDetail;
11
- }
12
- };
13
- var FRIENDLY_MESSAGES = {
14
- context_overflow: "The conversation is too long for this model. Try /undo to remove recent turns or /new to start fresh.",
15
- model_not_found: "The requested model was not found. Use /model to select a different one.",
16
- invalid_request: "The request was malformed and could not be processed.",
17
- auth_failed: "Authentication failed. Please verify your API key in ~/.autohand/config.json.",
18
- payment_required: "Payment required. Please check your account balance or billing settings.",
19
- access_denied: "Access denied. Your API key may not have permission for this model.",
20
- rate_limited: "Rate limit exceeded. Please wait a moment and try again, or choose a different model.",
21
- server_error: "The AI service encountered an error. Please try again later.",
22
- network_error: "Unable to connect to the AI service. Please check your internet connection.",
23
- timeout: "The request timed out. The AI service may be experiencing high load.",
24
- cancelled: "Request cancelled.",
25
- unknown: "An unexpected error occurred. Please try again."
26
- };
27
- var MODEL_NOT_FOUND_PATTERNS = [
28
- "invalid model",
29
- "model does not exist",
30
- "model not found",
31
- "no endpoints found for model",
32
- "does not exist or you do not have access",
33
- // Catch "model 'xyz' not found" where 'not found' is separate from 'model'
34
- "' not found",
35
- '" not found'
36
- ];
37
- var CONTEXT_OVERFLOW_PATTERNS = [
38
- "maximum context length",
39
- "context length exceeded",
40
- "context is too long",
41
- "prompt is too long",
42
- "reduce the length",
43
- "payload too large",
44
- "context window",
45
- "token limit",
46
- "tokens exceeds",
47
- "too many tokens"
48
- ];
49
- var CANCEL_PATTERNS = [
50
- "cancelled",
51
- "canceled",
52
- "aborted",
53
- "user force closed"
54
- ];
55
- var NETWORK_PATTERNS = [
56
- "econnrefused",
57
- "econnreset",
58
- "enotfound",
59
- "etimedout",
60
- "fetch failed",
61
- "network",
62
- "unable to connect"
63
- ];
64
- var TIMEOUT_PATTERNS = [
65
- "timed out",
66
- "timeout"
67
- ];
68
- function classifyApiError(httpStatus, errorBody, headers) {
69
- const lower = errorBody.toLowerCase();
70
- if (httpStatus === 401) {
71
- return makeError("auth_failed", httpStatus, false, errorBody, headers);
72
- }
73
- if (httpStatus === 402) {
74
- return makeError("payment_required", httpStatus, false, errorBody, headers);
75
- }
76
- if (httpStatus === 403) {
77
- return makeError("access_denied", httpStatus, false, errorBody, headers);
78
- }
79
- if (httpStatus === 404) {
80
- return makeError("model_not_found", httpStatus, false, errorBody, headers);
81
- }
82
- if (httpStatus === 429) {
83
- return makeError("rate_limited", httpStatus, true, errorBody, headers);
84
- }
85
- if (httpStatus === 504) {
86
- return makeError("timeout", httpStatus, true, errorBody, headers);
87
- }
88
- if (httpStatus >= 500) {
89
- return makeError("server_error", httpStatus, true, errorBody, headers);
90
- }
91
- if (httpStatus === 400) {
92
- if (matchesAny(lower, MODEL_NOT_FOUND_PATTERNS)) {
93
- return makeError("model_not_found", httpStatus, false, errorBody, headers);
94
- }
95
- if (matchesAny(lower, CONTEXT_OVERFLOW_PATTERNS)) {
96
- return makeError("context_overflow", httpStatus, true, errorBody, headers);
97
- }
98
- return makeError("invalid_request", httpStatus, false, errorBody, headers);
99
- }
100
- if (matchesAny(lower, CANCEL_PATTERNS)) {
101
- return makeError("cancelled", httpStatus, false, errorBody, headers);
102
- }
103
- if (matchesAny(lower, TIMEOUT_PATTERNS)) {
104
- return makeError("timeout", httpStatus, true, errorBody, headers);
105
- }
106
- if (matchesAny(lower, NETWORK_PATTERNS)) {
107
- return makeError("network_error", httpStatus, true, errorBody, headers);
108
- }
109
- if (httpStatus === 0 || httpStatus === void 0) {
110
- if (matchesAny(lower, CONTEXT_OVERFLOW_PATTERNS)) {
111
- return makeError("context_overflow", httpStatus, true, errorBody, headers);
112
- }
113
- if (matchesAny(lower, MODEL_NOT_FOUND_PATTERNS)) {
114
- return makeError("model_not_found", httpStatus, false, errorBody, headers);
115
- }
116
- }
117
- return makeError("unknown", httpStatus, true, errorBody, headers);
118
- }
119
- function matchesAny(lower, patterns) {
120
- return patterns.some((p) => lower.includes(p));
121
- }
122
- function makeError(code, httpStatus, retryable, rawBody, headers) {
123
- const friendlyMessage = FRIENDLY_MESSAGES[code];
124
- const message = rawBody ? `${friendlyMessage}
125
- ${rawBody}` : friendlyMessage;
126
- const retryAfterMs = parseRetryAfter(headers);
127
- return new ApiError(message, code, httpStatus, retryable, retryAfterMs, rawBody);
128
- }
129
- function parseRetryAfter(headers) {
130
- if (!headers) return void 0;
131
- const value = headers.get("retry-after");
132
- if (!value) return void 0;
133
- const seconds = Number(value);
134
- if (!Number.isNaN(seconds) && seconds > 0) {
135
- return seconds * 1e3;
136
- }
137
- const dateMs = Date.parse(value);
138
- if (!Number.isNaN(dateMs)) {
139
- const delayMs = dateMs - Date.now();
140
- return delayMs > 0 ? delayMs : void 0;
141
- }
142
- return void 0;
143
- }
144
-
145
- // src/providers/OllamaProvider.ts
146
- var DEFAULT_TIMEOUT = 12e4;
147
- var DEFAULT_CHUNK_TIMEOUT = 3e4;
148
- var DEFAULT_MAX_RETRIES = 2;
149
- var MAX_ALLOWED_RETRIES = 5;
150
- var DEFAULT_RETRY_DELAY = 1e3;
151
- var AVAILABILITY_TIMEOUT = 5e3;
152
- var OllamaProvider = class {
153
- constructor(config, networkSettings) {
154
- this.disableTools = false;
155
- this.baseUrl = config.baseUrl || "http://localhost:11434";
156
- this.model = config.model || "llama3.2:latest";
157
- const configuredRetries = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _ => _.maxRetries]), () => ( DEFAULT_MAX_RETRIES));
158
- this.maxRetries = Math.min(Math.max(0, configuredRetries), MAX_ALLOWED_RETRIES);
159
- this.retryDelay = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _2 => _2.retryDelay]), () => ( DEFAULT_RETRY_DELAY));
160
- this.timeout = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _3 => _3.timeout]), () => ( DEFAULT_TIMEOUT));
161
- this.chunkTimeout = DEFAULT_CHUNK_TIMEOUT;
162
- }
163
- getName() {
164
- return "ollama";
165
- }
166
- setModel(model) {
167
- this.model = model;
168
- }
169
- async listModels() {
170
- try {
171
- const controller = new AbortController();
172
- const timerId = setTimeout(() => controller.abort(), AVAILABILITY_TIMEOUT);
173
- try {
174
- const response = await fetch(`${this.baseUrl}/api/tags`, {
175
- signal: controller.signal
176
- });
177
- if (!response.ok) {
178
- return [];
179
- }
180
- const data = await response.json();
181
- return data.models.map((m) => m.name);
182
- } finally {
183
- clearTimeout(timerId);
184
- }
185
- } catch (e) {
186
- return [];
187
- }
188
- }
189
- async isAvailable() {
190
- try {
191
- const controller = new AbortController();
192
- const timerId = setTimeout(() => controller.abort(), AVAILABILITY_TIMEOUT);
193
- try {
194
- const response = await fetch(`${this.baseUrl}/api/tags`, {
195
- signal: controller.signal
196
- });
197
- return response.ok;
198
- } finally {
199
- clearTimeout(timerId);
200
- }
201
- } catch (e2) {
202
- return false;
203
- }
204
- }
205
- async complete(request) {
206
- const messages = request.messages.map((msg) => {
207
- const mapped = {
208
- role: msg.role,
209
- content: _nullishCoalesce(msg.content, () => ( ""))
210
- };
211
- if (msg.name) {
212
- mapped.name = msg.name;
213
- }
214
- if (msg.role === "tool" && msg.tool_call_id) {
215
- mapped.tool_call_id = msg.tool_call_id;
216
- }
217
- if (msg.role === "assistant" && msg.tool_calls) {
218
- mapped.tool_calls = msg.tool_calls;
219
- }
220
- return mapped;
221
- });
222
- const body = {
223
- model: request.model || this.model,
224
- messages,
225
- stream: request.stream || false
226
- };
227
- if (request.temperature !== void 0) {
228
- body.options = { temperature: request.temperature };
229
- }
230
- if (!this.disableTools && request.tools && request.tools.length > 0) {
231
- body.tools = request.tools.map((tool) => ({
232
- type: "function",
233
- function: {
234
- name: tool.name,
235
- description: tool.description,
236
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
237
- }
238
- }));
239
- }
240
- let lastError = null;
241
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
242
- try {
243
- return await this.makeRequest(body, request);
244
- } catch (error) {
245
- lastError = error;
246
- if (this.isNonRetryableError(error)) {
247
- throw error;
248
- }
249
- if (attempt < this.maxRetries) {
250
- const delay = this.retryDelay * Math.pow(2, attempt);
251
- await this.sleep(delay);
252
- }
253
- }
254
- }
255
- throw _nullishCoalesce(lastError, () => ( new ApiError(
256
- "Failed to communicate with Ollama. Please try again.",
257
- "network_error",
258
- 0,
259
- true
260
- )));
261
- }
262
- async makeRequest(body, request) {
263
- let response;
264
- try {
265
- const timeoutController = new AbortController();
266
- const timerId = setTimeout(() => timeoutController.abort(), this.timeout);
267
- const combinedSignal = request.signal ? this.combineSignals(request.signal, timeoutController.signal) : timeoutController.signal;
268
- try {
269
- response = await fetch(`${this.baseUrl}/api/chat`, {
270
- method: "POST",
271
- headers: {
272
- "Content-Type": "application/json"
273
- },
274
- body: JSON.stringify(body),
275
- signal: combinedSignal
276
- });
277
- } finally {
278
- clearTimeout(timerId);
279
- }
280
- } catch (error) {
281
- const err = error;
282
- if (err.name === "AbortError" && _optionalChain([request, 'access', _4 => _4.signal, 'optionalAccess', _5 => _5.aborted])) {
283
- throw new ApiError("Request cancelled.", "cancelled", 0, false);
284
- }
285
- if (err.name === "AbortError") {
286
- throw new ApiError(
287
- `Ollama request timed out after ${this.timeout / 1e3}s. Local inference can be slow \u2014 consider increasing the timeout in your config.`,
288
- "timeout",
289
- 0,
290
- true
291
- );
292
- }
293
- throw new ApiError(
294
- `Cannot connect to Ollama at ${this.baseUrl}. Make sure Ollama is running (try 'ollama serve').`,
295
- "network_error",
296
- 0,
297
- true
298
- );
299
- }
300
- if (!response.ok) {
301
- const apiError = await this.buildApiError(response, body);
302
- if (apiError === null) {
303
- return this.makeRequest(body, request);
304
- }
305
- throw apiError;
306
- }
307
- if (request.stream) {
308
- return this.handleStreamingResponse(response);
309
- }
310
- const data = await response.json();
311
- let toolCalls;
312
- if (data.message.tool_calls && Array.isArray(data.message.tool_calls)) {
313
- toolCalls = data.message.tool_calls.map((tc, index) => ({
314
- id: `ollama-tool-${Date.now()}-${index}`,
315
- type: "function",
316
- function: {
317
- name: tc.function.name,
318
- // Ollama returns arguments as object, convert to JSON string for consistency
319
- arguments: JSON.stringify(tc.function.arguments)
320
- }
321
- }));
322
- }
323
- let usage;
324
- if (data.prompt_eval_count !== void 0 || data.eval_count !== void 0) {
325
- usage = {
326
- promptTokens: _nullishCoalesce(data.prompt_eval_count, () => ( 0)),
327
- completionTokens: _nullishCoalesce(data.eval_count, () => ( 0)),
328
- totalTokens: (_nullishCoalesce(data.prompt_eval_count, () => ( 0))) + (_nullishCoalesce(data.eval_count, () => ( 0)))
329
- };
330
- }
331
- return {
332
- id: `ollama-${Date.now()}`,
333
- created: Math.floor(new Date(data.created_at).getTime() / 1e3),
334
- content: data.message.content,
335
- toolCalls,
336
- finishReason: _optionalChain([toolCalls, 'optionalAccess', _6 => _6.length]) ? "tool_calls" : "stop",
337
- usage,
338
- raw: data
339
- };
340
- }
341
- /**
342
- * Build an ApiError from a non-ok response.
343
- *
344
- * Returns `null` as a sentinel when the request was retried internally
345
- * (e.g., disableTools retry). The caller must re-run makeRequest in
346
- * that case.
347
- */
348
- async buildApiError(response, body) {
349
- let errorBody = "";
350
- try {
351
- errorBody = await response.text();
352
- } catch (e3) {
353
- }
354
- if (errorBody.includes("does not support tools") && body.tools) {
355
- console.warn(`Model ${body.model} does not support tools. Retrying without tool support.`);
356
- this.disableTools = true;
357
- delete body.tools;
358
- return null;
359
- }
360
- if (response.status === 404) {
361
- const baseError = classifyApiError(response.status, errorBody, response.headers);
362
- return new ApiError(
363
- `Model not found. Run 'ollama pull ${String(body.model)}' to download it.
364
- ${errorBody}`,
365
- baseError.code,
366
- baseError.httpStatus,
367
- baseError.retryable,
368
- baseError.retryAfterMs,
369
- errorBody
370
- );
371
- }
372
- return classifyApiError(response.status, errorBody, response.headers);
373
- }
374
- async handleStreamingResponse(response) {
375
- const reader = _optionalChain([response, 'access', _7 => _7.body, 'optionalAccess', _8 => _8.getReader, 'call', _9 => _9()]);
376
- if (!reader) {
377
- throw new Error("No response body");
378
- }
379
- const decoder = new TextDecoder();
380
- let fullContent = "";
381
- let lastData = null;
382
- let streamEndedWithDone = false;
383
- try {
384
- while (true) {
385
- const chunkResult = await this.readWithTimeout(reader, this.chunkTimeout, fullContent);
386
- if ("timedOut" in chunkResult) {
387
- if (fullContent) {
388
- return {
389
- id: `ollama-${Date.now()}`,
390
- created: lastData ? Math.floor(new Date(lastData.created_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3),
391
- content: fullContent,
392
- finishReason: "length",
393
- raw: lastData
394
- };
395
- }
396
- throw new ApiError(
397
- `Ollama stream timed out after ${this.chunkTimeout / 1e3}s with no data. Make sure Ollama is running and the model is loaded.`,
398
- "timeout",
399
- 0,
400
- true
401
- );
402
- }
403
- const { done, value } = chunkResult;
404
- if (done) {
405
- break;
406
- }
407
- const chunk = decoder.decode(value, { stream: true });
408
- const lines = chunk.split("\n").filter((line) => line.trim());
409
- for (const line of lines) {
410
- try {
411
- const data = JSON.parse(line);
412
- fullContent += data.message.content;
413
- lastData = data;
414
- if (data.done) {
415
- streamEndedWithDone = true;
416
- }
417
- } catch (e4) {
418
- }
419
- }
420
- if (streamEndedWithDone) {
421
- break;
422
- }
423
- }
424
- } finally {
425
- reader.releaseLock();
426
- }
427
- const finishReason = streamEndedWithDone ? "stop" : "length";
428
- return {
429
- id: `ollama-${Date.now()}`,
430
- created: lastData ? Math.floor(new Date(lastData.created_at).getTime() / 1e3) : Math.floor(Date.now() / 1e3),
431
- content: fullContent,
432
- finishReason,
433
- raw: lastData
434
- };
435
- }
436
- /**
437
- * Read one chunk from the stream with a timeout.
438
- * Returns `{ timedOut: true }` if the timeout fires before a chunk arrives.
439
- */
440
- async readWithTimeout(reader, timeoutMs, _partialContent) {
441
- let timerId;
442
- const timeoutPromise = new Promise((resolve) => {
443
- timerId = setTimeout(() => resolve({ timedOut: true }), timeoutMs);
444
- });
445
- try {
446
- const result = await Promise.race([
447
- reader.read(),
448
- timeoutPromise
449
- ]);
450
- return result;
451
- } finally {
452
- clearTimeout(timerId);
453
- }
454
- }
455
- isNonRetryableError(error) {
456
- if (error instanceof ApiError) {
457
- return !error.retryable;
458
- }
459
- const classified = classifyApiError(0, error.message);
460
- return !classified.retryable;
461
- }
462
- combineSignals(signal1, signal2) {
463
- const controller = new AbortController();
464
- const abort = () => controller.abort();
465
- signal1.addEventListener("abort", abort, { once: true });
466
- signal2.addEventListener("abort", abort, { once: true });
467
- if (signal1.aborted || signal2.aborted) {
468
- controller.abort();
469
- }
470
- return controller.signal;
471
- }
472
- sleep(ms) {
473
- return new Promise((resolve) => setTimeout(resolve, ms));
474
- }
475
- };
476
-
477
- // src/providers/OpenAIProvider.ts
478
- var OpenAIProvider = class {
479
- constructor(config) {
480
- this.baseUrl = config.baseUrl || "https://api.openai.com/v1";
481
- this.apiKey = config.apiKey || "";
482
- this.model = config.model || "gpt-4o";
483
- }
484
- getName() {
485
- return "openai";
486
- }
487
- setModel(model) {
488
- this.model = model;
489
- }
490
- async listModels() {
491
- return [
492
- "gpt-4o",
493
- "gpt-4o-mini",
494
- "gpt-4-turbo",
495
- "gpt-4",
496
- "gpt-3.5-turbo"
497
- ];
498
- }
499
- async isAvailable() {
500
- try {
501
- const response = await fetch(`${this.baseUrl}/models`, {
502
- headers: {
503
- "Authorization": `Bearer ${this.apiKey}`
504
- }
505
- });
506
- return response.ok;
507
- } catch (e5) {
508
- return false;
509
- }
510
- }
511
- async complete(request) {
512
- const body = {
513
- model: request.model || this.model,
514
- messages: request.messages.map((msg) => {
515
- const mapped = {
516
- role: msg.role === "system" ? "system" : msg.role === "user" ? "user" : msg.role === "tool" ? "tool" : "assistant",
517
- content: msg.content
518
- };
519
- if (msg.role === "tool" && msg.tool_call_id) {
520
- mapped.tool_call_id = msg.tool_call_id;
521
- }
522
- if (msg.name) {
523
- mapped.name = msg.name;
524
- }
525
- return mapped;
526
- }),
527
- temperature: request.temperature || 0.7,
528
- max_tokens: request.maxTokens
529
- };
530
- if (request.tools && request.tools.length > 0) {
531
- body.tools = request.tools.map((tool) => ({
532
- type: "function",
533
- function: {
534
- name: tool.name,
535
- description: tool.description,
536
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
537
- }
538
- }));
539
- if (request.toolChoice) {
540
- body.tool_choice = request.toolChoice;
541
- }
542
- }
543
- const response = await fetch(`${this.baseUrl}/chat/completions`, {
544
- method: "POST",
545
- headers: {
546
- "Content-Type": "application/json",
547
- "Authorization": `Bearer ${this.apiKey}`
548
- },
549
- body: JSON.stringify(body),
550
- signal: request.signal
551
- });
552
- if (!response.ok) {
553
- const error = await response.text();
554
- throw new Error(`OpenAI API error: ${response.status} ${error}`);
555
- }
556
- const data = await response.json();
557
- const message = data.choices[0].message;
558
- const finishReason = data.choices[0].finish_reason;
559
- let toolCalls;
560
- if (message.tool_calls && Array.isArray(message.tool_calls)) {
561
- toolCalls = message.tool_calls.map((tc) => ({
562
- id: tc.id,
563
- type: "function",
564
- function: {
565
- name: tc.function.name,
566
- arguments: tc.function.arguments
567
- }
568
- }));
569
- }
570
- let usage;
571
- if (data.usage) {
572
- usage = {
573
- promptTokens: data.usage.prompt_tokens,
574
- completionTokens: data.usage.completion_tokens,
575
- totalTokens: data.usage.total_tokens
576
- };
577
- }
578
- return {
579
- id: data.id,
580
- created: data.created,
581
- content: _nullishCoalesce(message.content, () => ( "")),
582
- toolCalls,
583
- finishReason,
584
- usage,
585
- raw: data
586
- };
587
- }
588
- };
589
-
590
- // src/providers/LlamaCppProvider.ts
591
- var LlamaCppProvider = class {
592
- constructor(config) {
593
- const port = config.port || 8080;
594
- this.baseUrl = config.baseUrl || `http://localhost:${port}`;
595
- this.model = config.model || "llama-model";
596
- }
597
- getName() {
598
- return "llamacpp";
599
- }
600
- setModel(model) {
601
- this.model = model;
602
- }
603
- async listModels() {
604
- try {
605
- const response = await fetch(`${this.baseUrl}/v1/models`);
606
- if (!response.ok) {
607
- return this.model ? [this.model] : [];
608
- }
609
- const data = await response.json();
610
- return _nullishCoalesce(_optionalChain([data, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.map, 'call', _12 => _12((m) => m.id)]), () => ( [this.model]));
611
- } catch (e6) {
612
- return this.model ? [this.model] : [];
613
- }
614
- }
615
- async isAvailable() {
616
- try {
617
- const response = await fetch(`${this.baseUrl}/health`);
618
- return response.ok;
619
- } catch (e7) {
620
- return false;
621
- }
622
- }
623
- async complete(request) {
624
- const body = {
625
- model: request.model || this.model,
626
- messages: request.messages.map((msg) => {
627
- const mapped = {
628
- role: msg.role,
629
- content: msg.content
630
- };
631
- if (msg.name) mapped.name = msg.name;
632
- if (msg.role === "tool" && msg.tool_call_id) mapped.tool_call_id = msg.tool_call_id;
633
- if (msg.role === "assistant" && msg.tool_calls) mapped.tool_calls = msg.tool_calls;
634
- return mapped;
635
- }),
636
- temperature: _nullishCoalesce(request.temperature, () => ( 0.7)),
637
- max_tokens: _nullishCoalesce(request.maxTokens, () => ( 4096)),
638
- stream: false
639
- };
640
- if (request.tools && request.tools.length > 0) {
641
- body.tools = request.tools.map((tool) => ({
642
- type: "function",
643
- function: {
644
- name: tool.name,
645
- description: tool.description,
646
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
647
- }
648
- }));
649
- }
650
- const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
651
- method: "POST",
652
- headers: {
653
- "Content-Type": "application/json"
654
- },
655
- body: JSON.stringify(body),
656
- signal: request.signal
657
- });
658
- if (!response.ok) {
659
- throw new Error(`llama.cpp API error: ${response.status} ${response.statusText}`);
660
- }
661
- const data = await response.json();
662
- const choice = data.choices[0];
663
- let toolCalls;
664
- if (_optionalChain([choice, 'optionalAccess', _13 => _13.message, 'access', _14 => _14.tool_calls, 'optionalAccess', _15 => _15.length])) {
665
- toolCalls = choice.message.tool_calls.map((tc) => ({
666
- id: tc.id,
667
- type: "function",
668
- function: {
669
- name: tc.function.name,
670
- arguments: tc.function.arguments
671
- }
672
- }));
673
- }
674
- let usage;
675
- if (data.usage) {
676
- usage = {
677
- promptTokens: data.usage.prompt_tokens,
678
- completionTokens: data.usage.completion_tokens,
679
- totalTokens: data.usage.total_tokens
680
- };
681
- }
682
- const finishReason = _optionalChain([toolCalls, 'optionalAccess', _16 => _16.length]) ? "tool_calls" : _optionalChain([choice, 'optionalAccess', _17 => _17.finish_reason]) === "stop" || _optionalChain([choice, 'optionalAccess', _18 => _18.finish_reason]) === "length" || _optionalChain([choice, 'optionalAccess', _19 => _19.finish_reason]) === "content_filter" ? choice.finish_reason : "stop";
683
- return {
684
- id: data.id || `llamacpp-${Date.now()}`,
685
- created: data.created || Math.floor(Date.now() / 1e3),
686
- content: _nullishCoalesce(_optionalChain([choice, 'optionalAccess', _20 => _20.message, 'access', _21 => _21.content]), () => ( "")),
687
- toolCalls,
688
- finishReason,
689
- usage,
690
- raw: data
691
- };
692
- }
693
- };
694
-
695
- // src/providers/OpenRouterClient.ts
696
- function sanitizeMessages(messages) {
697
- return messages.map((msg) => {
698
- const sanitized = {
699
- role: msg.role,
700
- content: msg.content
701
- };
702
- if (msg.role === "tool" && msg.tool_call_id) {
703
- sanitized.tool_call_id = msg.tool_call_id;
704
- }
705
- if (msg.role === "assistant" && _optionalChain([msg, 'access', _22 => _22.tool_calls, 'optionalAccess', _23 => _23.length])) {
706
- sanitized.tool_calls = msg.tool_calls;
707
- }
708
- if (msg.name) {
709
- sanitized.name = msg.name;
710
- }
711
- return sanitized;
712
- });
713
- }
714
- var DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
715
- var DEFAULT_MAX_RETRIES2 = 3;
716
- var MAX_ALLOWED_RETRIES2 = 5;
717
- var DEFAULT_RETRY_DELAY2 = 1e3;
718
- var DEFAULT_TIMEOUT2 = 3e4;
719
- var OpenRouterClient = class {
720
- constructor(settings, networkSettings) {
721
- this.apiKey = _nullishCoalesce(settings.apiKey, () => ( ""));
722
- this.baseUrl = _nullishCoalesce(settings.baseUrl, () => ( DEFAULT_BASE_URL));
723
- this.defaultModel = settings.model;
724
- const configuredRetries = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _24 => _24.maxRetries]), () => ( DEFAULT_MAX_RETRIES2));
725
- this.maxRetries = Math.min(
726
- Math.max(0, configuredRetries),
727
- MAX_ALLOWED_RETRIES2
728
- );
729
- this.retryDelay = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _25 => _25.retryDelay]), () => ( DEFAULT_RETRY_DELAY2));
730
- this.timeout = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _26 => _26.timeout]), () => ( DEFAULT_TIMEOUT2));
731
- }
732
- setDefaultModel(model) {
733
- this.defaultModel = model;
734
- }
735
- async complete(request) {
736
- const payload = {
737
- model: _nullishCoalesce(request.model, () => ( this.defaultModel)),
738
- messages: sanitizeMessages(request.messages),
739
- temperature: _nullishCoalesce(request.temperature, () => ( 0.2)),
740
- max_tokens: _nullishCoalesce(request.maxTokens, () => ( 16e3)),
741
- // Increased from 1000 to allow large file generation
742
- stream: _nullishCoalesce(request.stream, () => ( false))
743
- };
744
- if (request.tools && request.tools.length > 0) {
745
- payload.tools = request.tools.map((tool) => ({
746
- type: "function",
747
- function: {
748
- name: tool.name,
749
- description: tool.description,
750
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
751
- }
752
- }));
753
- if (request.toolChoice) {
754
- payload.tool_choice = request.toolChoice;
755
- }
756
- }
757
- const model = (_nullishCoalesce(request.model, () => ( this.defaultModel))).toLowerCase();
758
- if (request.thinkingLevel && request.thinkingLevel !== "normal") {
759
- if (model.includes("o1") || model.includes("o3")) {
760
- if (request.thinkingLevel === "extended") {
761
- payload.reasoning_effort = "high";
762
- } else if (request.thinkingLevel === "none") {
763
- payload.reasoning_effort = "low";
764
- }
765
- }
766
- if (model.includes("claude") && request.thinkingLevel === "extended") {
767
- payload.provider = {
768
- anthropic: {
769
- thinking: {
770
- type: "enabled",
771
- budget_tokens: 1e4
772
- }
773
- }
774
- };
775
- }
776
- }
777
- const headers = {
778
- "Content-Type": "application/json",
779
- "HTTP-Referer": "https://autohand.dev",
780
- "X-OpenRouter-Title": "Autohand Code CLI",
781
- "X-OpenRouter-Categories": "cli-agent"
782
- };
783
- if (this.apiKey) {
784
- headers.Authorization = `Bearer ${this.apiKey}`;
785
- }
786
- const payloadJson = JSON.stringify(payload);
787
- const payloadSizeBytes = payloadJson.length;
788
- const maxPayloadSize = 5 * 1024 * 1024;
789
- if (payloadSizeBytes > maxPayloadSize) {
790
- const sizeMB = (payloadSizeBytes / (1024 * 1024)).toFixed(2);
791
- throw new ApiError(
792
- `Request payload too large (${sizeMB}MB). This usually happens when the conversation history grows too long. Try using /undo to remove recent turns or /new to start fresh.`,
793
- "context_overflow",
794
- 400,
795
- true
796
- );
797
- }
798
- let lastError = null;
799
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
800
- try {
801
- const response = await this.makeRequest(
802
- payload,
803
- headers,
804
- request.signal,
805
- payloadJson
806
- );
807
- return response;
808
- } catch (error) {
809
- lastError = error;
810
- if (this.isNonRetryableError(error)) {
811
- throw error;
812
- }
813
- if (attempt < this.maxRetries) {
814
- const delay = this.retryDelay * Math.pow(2, attempt);
815
- await this.sleep(delay);
816
- }
817
- }
818
- }
819
- throw _nullishCoalesce(lastError, () => ( new ApiError("Failed to communicate with the AI service. Please try again.", "network_error", 0, true)));
820
- }
821
- async makeRequest(payload, headers, signal, preSerializedBody) {
822
- let response;
823
- try {
824
- const timeoutController = new AbortController();
825
- const timeoutId = setTimeout(
826
- () => timeoutController.abort(),
827
- this.timeout
828
- );
829
- const combinedSignal = signal ? this.combineSignals(signal, timeoutController.signal) : timeoutController.signal;
830
- try {
831
- response = await fetch(`${this.baseUrl}/chat/completions`, {
832
- method: "POST",
833
- headers,
834
- body: _nullishCoalesce(preSerializedBody, () => ( JSON.stringify(payload))),
835
- signal: combinedSignal
836
- });
837
- } finally {
838
- clearTimeout(timeoutId);
839
- }
840
- } catch (error) {
841
- const err = error;
842
- if (err.name === "AbortError" && _optionalChain([signal, 'optionalAccess', _27 => _27.aborted])) {
843
- throw new ApiError("Request cancelled.", "cancelled", 0, false);
844
- }
845
- if (err.name === "AbortError") {
846
- throw new ApiError(
847
- "Request timed out. The AI service may be experiencing high load.",
848
- "timeout",
849
- 0,
850
- true
851
- );
852
- }
853
- throw new ApiError(
854
- "Unable to connect to the AI service. Please check your internet connection.",
855
- "network_error",
856
- 0,
857
- true
858
- );
859
- }
860
- if (!response.ok) {
861
- throw await this.buildApiError(response);
862
- }
863
- const json = await response.json();
864
- const message = _optionalChain([json, 'optionalAccess', _28 => _28.choices, 'optionalAccess', _29 => _29[0], 'optionalAccess', _30 => _30.message]);
865
- const text = _nullishCoalesce(_optionalChain([message, 'optionalAccess', _31 => _31.content]), () => ( ""));
866
- const finishReason = _optionalChain([json, 'optionalAccess', _32 => _32.choices, 'optionalAccess', _33 => _33[0], 'optionalAccess', _34 => _34.finish_reason]);
867
- let toolCalls;
868
- if (_optionalChain([message, 'optionalAccess', _35 => _35.tool_calls]) && Array.isArray(message.tool_calls)) {
869
- toolCalls = message.tool_calls.map((tc) => {
870
- const rawArgs = _optionalChain([tc, 'access', _36 => _36.function, 'optionalAccess', _37 => _37.arguments]);
871
- return {
872
- id: tc.id,
873
- type: "function",
874
- function: {
875
- name: _nullishCoalesce(_optionalChain([tc, 'access', _38 => _38.function, 'optionalAccess', _39 => _39.name]), () => ( "")),
876
- arguments: _nullishCoalesce(rawArgs, () => ( "{}"))
877
- }
878
- };
879
- });
880
- }
881
- let usage;
882
- if (_optionalChain([json, 'optionalAccess', _40 => _40.usage])) {
883
- usage = {
884
- promptTokens: _nullishCoalesce(json.usage.prompt_tokens, () => ( 0)),
885
- completionTokens: _nullishCoalesce(json.usage.completion_tokens, () => ( 0)),
886
- totalTokens: _nullishCoalesce(json.usage.total_tokens, () => ( 0))
887
- };
888
- }
889
- return {
890
- id: _nullishCoalesce(json.id, () => ( "autohand-local")),
891
- created: _nullishCoalesce(json.created, () => ( Date.now())),
892
- content: text,
893
- toolCalls,
894
- finishReason,
895
- usage,
896
- raw: json
897
- };
898
- }
899
- async buildApiError(response) {
900
- const status = response.status;
901
- let errorDetail = "";
902
- try {
903
- const body = await response.json();
904
- errorDetail = _optionalChain([body, 'optionalAccess', _41 => _41.error, 'optionalAccess', _42 => _42.message]) || _optionalChain([body, 'optionalAccess', _43 => _43.error]) || _optionalChain([body, 'optionalAccess', _44 => _44.message]) || "";
905
- if (typeof errorDetail === "object") {
906
- errorDetail = JSON.stringify(errorDetail);
907
- }
908
- } catch (e8) {
909
- try {
910
- errorDetail = await response.text();
911
- } catch (e9) {
912
- }
913
- }
914
- return classifyApiError(status, errorDetail, response.headers);
915
- }
916
- isNonRetryableError(error) {
917
- if (error instanceof ApiError) {
918
- return !error.retryable;
919
- }
920
- const classified = classifyApiError(0, error.message);
921
- return !classified.retryable;
922
- }
923
- combineSignals(signal1, signal2) {
924
- const controller = new AbortController();
925
- const abort = () => controller.abort();
926
- signal1.addEventListener("abort", abort, { once: true });
927
- signal2.addEventListener("abort", abort, { once: true });
928
- if (signal1.aborted || signal2.aborted) {
929
- controller.abort();
930
- }
931
- return controller.signal;
932
- }
933
- sleep(ms) {
934
- return new Promise((resolve) => setTimeout(resolve, ms));
935
- }
936
- };
937
-
938
- // src/providers/OpenRouterProvider.ts
939
- var OpenRouterProvider = class {
940
- constructor(config, networkSettings) {
941
- this.client = new OpenRouterClient(config, networkSettings);
942
- this.model = config.model;
943
- }
944
- getName() {
945
- return "openrouter";
946
- }
947
- setModel(model) {
948
- this.model = model;
949
- this.client.setDefaultModel(model);
950
- }
951
- async listModels() {
952
- return [
953
- "anthropic/claude-3.5-sonnet",
954
- "anthropic/claude-3-opus",
955
- "google/gemini-pro-1.5",
956
- "openai/gpt-4o",
957
- "x-ai/grok-2-latest",
958
- "meta-llama/llama-3.1-70b-instruct"
959
- ];
960
- }
961
- async isAvailable() {
962
- return true;
963
- }
964
- async complete(request) {
965
- return this.client.complete(request);
966
- }
967
- };
968
-
969
- // src/utils/platform.ts
970
- function isAppleSilicon() {
971
- return process.platform === "darwin" && process.arch === "arm64";
972
- }
973
- function isMLXSupported() {
974
- return isAppleSilicon();
975
- }
976
-
977
- // src/providers/MLXProvider.ts
978
- var DEFAULT_TIMEOUT3 = 6e4;
979
- var DEFAULT_MAX_RETRIES3 = 2;
980
- var MAX_ALLOWED_RETRIES3 = 5;
981
- var DEFAULT_RETRY_DELAY3 = 1e3;
982
- var AVAILABILITY_TIMEOUT2 = 5e3;
983
- var MLXProvider = class {
984
- constructor(config, networkSettings) {
985
- const port = config.port || 8080;
986
- this.baseUrl = config.baseUrl || `http://localhost:${port}`;
987
- this.model = config.model || "mlx-model";
988
- const configuredRetries = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _45 => _45.maxRetries]), () => ( DEFAULT_MAX_RETRIES3));
989
- this.maxRetries = Math.min(Math.max(0, configuredRetries), MAX_ALLOWED_RETRIES3);
990
- this.retryDelay = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _46 => _46.retryDelay]), () => ( DEFAULT_RETRY_DELAY3));
991
- this.timeout = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _47 => _47.timeout]), () => ( DEFAULT_TIMEOUT3));
992
- }
993
- getName() {
994
- return "mlx";
995
- }
996
- setModel(model) {
997
- this.model = model;
998
- }
999
- async listModels() {
1000
- if (!isMLXSupported()) {
1001
- return [];
1002
- }
1003
- try {
1004
- const controller = new AbortController();
1005
- const timerId = setTimeout(() => controller.abort(), AVAILABILITY_TIMEOUT2);
1006
- try {
1007
- const response = await fetch(`${this.baseUrl}/v1/models`, {
1008
- signal: controller.signal
1009
- });
1010
- if (!response.ok) {
1011
- return this.model ? [this.model] : [];
1012
- }
1013
- const data = await response.json();
1014
- return _nullishCoalesce(_optionalChain([data, 'access', _48 => _48.data, 'optionalAccess', _49 => _49.map, 'call', _50 => _50((m) => m.id)]), () => ( (this.model ? [this.model] : [])));
1015
- } finally {
1016
- clearTimeout(timerId);
1017
- }
1018
- } catch (e10) {
1019
- return this.model ? [this.model] : [];
1020
- }
1021
- }
1022
- async isAvailable() {
1023
- if (!isMLXSupported()) {
1024
- return false;
1025
- }
1026
- try {
1027
- const controller = new AbortController();
1028
- const timerId = setTimeout(() => controller.abort(), AVAILABILITY_TIMEOUT2);
1029
- try {
1030
- const response = await fetch(`${this.baseUrl}/v1/models`, {
1031
- signal: controller.signal
1032
- });
1033
- return response.ok;
1034
- } finally {
1035
- clearTimeout(timerId);
1036
- }
1037
- } catch (e11) {
1038
- return false;
1039
- }
1040
- }
1041
- async complete(request) {
1042
- if (!isMLXSupported()) {
1043
- throw new Error("MLX is only supported on macOS with Apple Silicon");
1044
- }
1045
- const body = {
1046
- model: request.model || this.model,
1047
- messages: request.messages.map((msg) => {
1048
- const mapped = {
1049
- role: msg.role,
1050
- content: msg.content
1051
- };
1052
- if (msg.name) mapped.name = msg.name;
1053
- if (msg.role === "tool" && msg.tool_call_id) mapped.tool_call_id = msg.tool_call_id;
1054
- if (msg.role === "assistant" && msg.tool_calls) mapped.tool_calls = msg.tool_calls;
1055
- return mapped;
1056
- }),
1057
- temperature: _nullishCoalesce(request.temperature, () => ( 0.7)),
1058
- max_tokens: _nullishCoalesce(request.maxTokens, () => ( 4096)),
1059
- stream: false
1060
- };
1061
- if (request.tools && request.tools.length > 0) {
1062
- body.tools = request.tools.map((tool) => ({
1063
- type: "function",
1064
- function: {
1065
- name: tool.name,
1066
- description: tool.description,
1067
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
1068
- }
1069
- }));
1070
- }
1071
- let lastError = null;
1072
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
1073
- try {
1074
- return await this.makeRequest(body, request.signal);
1075
- } catch (error) {
1076
- lastError = error;
1077
- if (this.isNonRetryableError(error)) {
1078
- throw error;
1079
- }
1080
- if (attempt < this.maxRetries) {
1081
- const delay = this.retryDelay * Math.pow(2, attempt);
1082
- await this.sleep(delay);
1083
- }
1084
- }
1085
- }
1086
- throw _nullishCoalesce(lastError, () => ( new ApiError(
1087
- "Failed to communicate with the MLX server. Please try again.",
1088
- "network_error",
1089
- 0,
1090
- true
1091
- )));
1092
- }
1093
- async makeRequest(body, userSignal) {
1094
- let response;
1095
- try {
1096
- const timeoutController = new AbortController();
1097
- const timerId = setTimeout(() => timeoutController.abort(), this.timeout);
1098
- const combinedSignal = userSignal ? this.combineSignals(userSignal, timeoutController.signal) : timeoutController.signal;
1099
- try {
1100
- response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
1101
- method: "POST",
1102
- headers: {
1103
- "Content-Type": "application/json"
1104
- },
1105
- body: JSON.stringify(body),
1106
- signal: combinedSignal
1107
- });
1108
- } finally {
1109
- clearTimeout(timerId);
1110
- }
1111
- } catch (error) {
1112
- const err = error;
1113
- if (err.name === "AbortError" && _optionalChain([userSignal, 'optionalAccess', _51 => _51.aborted])) {
1114
- throw new ApiError("Request cancelled.", "cancelled", 0, false);
1115
- }
1116
- if (err.name === "AbortError") {
1117
- throw new ApiError(
1118
- `MLX server request timed out after ${this.timeout / 1e3}s. Local inference can be slow \u2014 consider increasing the timeout in your config.`,
1119
- "timeout",
1120
- 0,
1121
- true
1122
- );
1123
- }
1124
- throw new ApiError(
1125
- `Cannot connect to MLX server at ${this.baseUrl}. Make sure it is running.`,
1126
- "network_error",
1127
- 0,
1128
- true
1129
- );
1130
- }
1131
- if (!response.ok) {
1132
- throw await this.buildApiError(response);
1133
- }
1134
- const data = await response.json();
1135
- const choice = data.choices[0];
1136
- let toolCalls;
1137
- if (_optionalChain([choice, 'optionalAccess', _52 => _52.message, 'access', _53 => _53.tool_calls, 'optionalAccess', _54 => _54.length])) {
1138
- toolCalls = choice.message.tool_calls.map((tc) => ({
1139
- id: tc.id,
1140
- type: "function",
1141
- function: {
1142
- name: tc.function.name,
1143
- arguments: tc.function.arguments
1144
- }
1145
- }));
1146
- }
1147
- let usage;
1148
- if (data.usage) {
1149
- usage = {
1150
- promptTokens: data.usage.prompt_tokens,
1151
- completionTokens: data.usage.completion_tokens,
1152
- totalTokens: data.usage.total_tokens
1153
- };
1154
- }
1155
- const finishReason = _optionalChain([toolCalls, 'optionalAccess', _55 => _55.length]) ? "tool_calls" : _optionalChain([choice, 'optionalAccess', _56 => _56.finish_reason]) === "stop" || _optionalChain([choice, 'optionalAccess', _57 => _57.finish_reason]) === "length" || _optionalChain([choice, 'optionalAccess', _58 => _58.finish_reason]) === "content_filter" ? choice.finish_reason : "stop";
1156
- return {
1157
- id: data.id || `mlx-${Date.now()}`,
1158
- created: data.created || Math.floor(Date.now() / 1e3),
1159
- content: _nullishCoalesce(_optionalChain([choice, 'optionalAccess', _59 => _59.message, 'access', _60 => _60.content]), () => ( "")),
1160
- toolCalls,
1161
- finishReason,
1162
- usage,
1163
- raw: data
1164
- };
1165
- }
1166
- async buildApiError(response) {
1167
- let errorDetail = "";
1168
- try {
1169
- const body = await response.json();
1170
- const maybeError = _optionalChain([body, 'optionalAccess', _61 => _61.error]);
1171
- if (maybeError && typeof maybeError === "object") {
1172
- errorDetail = _nullishCoalesce(_optionalChain([maybeError, 'optionalAccess', _62 => _62.message]), () => ( ""));
1173
- } else if (typeof maybeError === "string") {
1174
- errorDetail = maybeError;
1175
- } else if (typeof _optionalChain([body, 'optionalAccess', _63 => _63.message]) === "string") {
1176
- errorDetail = body.message;
1177
- }
1178
- if (typeof errorDetail === "object") {
1179
- errorDetail = JSON.stringify(errorDetail);
1180
- }
1181
- } catch (e12) {
1182
- try {
1183
- errorDetail = await response.text();
1184
- } catch (e13) {
1185
- }
1186
- }
1187
- return classifyApiError(response.status, errorDetail, response.headers);
1188
- }
1189
- isNonRetryableError(error) {
1190
- if (error instanceof ApiError) {
1191
- return !error.retryable;
1192
- }
1193
- const classified = classifyApiError(0, error.message);
1194
- return !classified.retryable;
1195
- }
1196
- combineSignals(signal1, signal2) {
1197
- const controller = new AbortController();
1198
- const abort = () => controller.abort();
1199
- signal1.addEventListener("abort", abort, { once: true });
1200
- signal2.addEventListener("abort", abort, { once: true });
1201
- if (signal1.aborted || signal2.aborted) {
1202
- controller.abort();
1203
- }
1204
- return controller.signal;
1205
- }
1206
- sleep(ms) {
1207
- return new Promise((resolve) => setTimeout(resolve, ms));
1208
- }
1209
- };
1210
-
1211
- // src/providers/LLMGatewayClient.ts
1212
- function sanitizeMessages2(messages) {
1213
- return messages.map((msg) => {
1214
- const sanitized = {
1215
- role: msg.role,
1216
- content: msg.content
1217
- };
1218
- if (msg.role === "tool" && msg.tool_call_id) {
1219
- sanitized.tool_call_id = msg.tool_call_id;
1220
- }
1221
- if (msg.role === "assistant" && _optionalChain([msg, 'access', _64 => _64.tool_calls, 'optionalAccess', _65 => _65.length])) {
1222
- sanitized.tool_calls = msg.tool_calls;
1223
- }
1224
- if (msg.name) {
1225
- sanitized.name = msg.name;
1226
- }
1227
- return sanitized;
1228
- });
1229
- }
1230
- var DEFAULT_BASE_URL2 = "https://api.llmgateway.io/v1";
1231
- var DEFAULT_MAX_RETRIES4 = 3;
1232
- var MAX_ALLOWED_RETRIES4 = 5;
1233
- var DEFAULT_RETRY_DELAY4 = 1e3;
1234
- var DEFAULT_TIMEOUT4 = 3e4;
1235
- var FRIENDLY_ERRORS = {
1236
- 400: "The request was malformed. This often happens when the context is too long. Try /undo to remove recent turns or /new to start fresh.",
1237
- 401: "Authentication failed. Please verify your LLM Gateway API key in ~/.autohand/config.json.",
1238
- 402: "Payment required. Please check your LLM Gateway account balance or billing settings.",
1239
- 403: "Access denied. Your API key may not have permission for this model.",
1240
- 404: "The requested model was not found. Use /model to select a different one.",
1241
- 429: "Rate limit exceeded. Please wait a moment and try again, or choose a different model.",
1242
- 500: "The LLM Gateway service encountered an internal error. Please try again later.",
1243
- 502: "The LLM Gateway service is temporarily unavailable. Please try again in a few moments.",
1244
- 503: "The LLM Gateway service is currently overloaded. Please try again later.",
1245
- 504: "The request timed out. The service may be experiencing high load."
1246
- };
1247
- var LLMGatewayClient = class {
1248
- constructor(settings, networkSettings) {
1249
- this.apiKey = _nullishCoalesce(settings.apiKey, () => ( ""));
1250
- this.baseUrl = _nullishCoalesce(settings.baseUrl, () => ( DEFAULT_BASE_URL2));
1251
- this.defaultModel = settings.model;
1252
- const configuredRetries = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _66 => _66.maxRetries]), () => ( DEFAULT_MAX_RETRIES4));
1253
- this.maxRetries = Math.min(
1254
- Math.max(0, configuredRetries),
1255
- MAX_ALLOWED_RETRIES4
1256
- );
1257
- this.retryDelay = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _67 => _67.retryDelay]), () => ( DEFAULT_RETRY_DELAY4));
1258
- this.timeout = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _68 => _68.timeout]), () => ( DEFAULT_TIMEOUT4));
1259
- }
1260
- setDefaultModel(model) {
1261
- this.defaultModel = model;
1262
- }
1263
- async complete(request) {
1264
- const payload = {
1265
- model: _nullishCoalesce(request.model, () => ( this.defaultModel)),
1266
- messages: sanitizeMessages2(request.messages),
1267
- temperature: _nullishCoalesce(request.temperature, () => ( 0.2)),
1268
- max_tokens: _nullishCoalesce(request.maxTokens, () => ( 16e3)),
1269
- stream: _nullishCoalesce(request.stream, () => ( false))
1270
- };
1271
- if (request.tools && request.tools.length > 0) {
1272
- payload.tools = request.tools.map((tool) => ({
1273
- type: "function",
1274
- function: {
1275
- name: tool.name,
1276
- description: tool.description,
1277
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
1278
- }
1279
- }));
1280
- if (request.toolChoice) {
1281
- payload.tool_choice = request.toolChoice;
1282
- }
1283
- }
1284
- const headers = {
1285
- "Content-Type": "application/json"
1286
- };
1287
- if (this.apiKey) {
1288
- headers.Authorization = `Bearer ${this.apiKey}`;
1289
- }
1290
- const payloadJson = JSON.stringify(payload);
1291
- const payloadSizeBytes = payloadJson.length;
1292
- const maxPayloadSize = 5 * 1024 * 1024;
1293
- if (payloadSizeBytes > maxPayloadSize) {
1294
- const sizeMB = (payloadSizeBytes / (1024 * 1024)).toFixed(2);
1295
- throw new Error(
1296
- `Request payload too large (${sizeMB}MB). This usually happens when the conversation history grows too long. Try using /undo to remove recent turns or /new to start fresh.`
1297
- );
1298
- }
1299
- let lastError = null;
1300
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
1301
- try {
1302
- const response = await this.makeRequest(
1303
- payload,
1304
- headers,
1305
- request.signal,
1306
- payloadJson
1307
- );
1308
- return response;
1309
- } catch (error) {
1310
- lastError = error;
1311
- if (this.isNonRetryableError(error)) {
1312
- throw error;
1313
- }
1314
- if (attempt < this.maxRetries) {
1315
- const delay = this.retryDelay * Math.pow(2, attempt);
1316
- await this.sleep(delay);
1317
- }
1318
- }
1319
- }
1320
- throw _nullishCoalesce(lastError, () => ( new Error("Failed to communicate with LLM Gateway. Please try again.")));
1321
- }
1322
- async makeRequest(payload, headers, signal, preSerializedBody) {
1323
- let response;
1324
- try {
1325
- const timeoutController = new AbortController();
1326
- const timeoutId = setTimeout(
1327
- () => timeoutController.abort(),
1328
- this.timeout
1329
- );
1330
- const combinedSignal = signal ? this.combineSignals(signal, timeoutController.signal) : timeoutController.signal;
1331
- try {
1332
- response = await fetch(`${this.baseUrl}/chat/completions`, {
1333
- method: "POST",
1334
- headers,
1335
- body: _nullishCoalesce(preSerializedBody, () => ( JSON.stringify(payload))),
1336
- signal: combinedSignal
1337
- });
1338
- } finally {
1339
- clearTimeout(timeoutId);
1340
- }
1341
- } catch (error) {
1342
- const err = error;
1343
- if (err.name === "AbortError" && _optionalChain([signal, 'optionalAccess', _69 => _69.aborted])) {
1344
- throw new Error("Request cancelled.");
1345
- }
1346
- if (err.name === "AbortError") {
1347
- throw new Error(
1348
- "Request timed out. The LLM Gateway service may be experiencing high load."
1349
- );
1350
- }
1351
- throw new Error(
1352
- "Unable to connect to LLM Gateway. Please check your internet connection."
1353
- );
1354
- }
1355
- if (!response.ok) {
1356
- throw new Error(await this.buildFriendlyError(response));
1357
- }
1358
- const json = await response.json();
1359
- const message = _optionalChain([json, 'optionalAccess', _70 => _70.choices, 'optionalAccess', _71 => _71[0], 'optionalAccess', _72 => _72.message]);
1360
- const text = _nullishCoalesce(_optionalChain([message, 'optionalAccess', _73 => _73.content]), () => ( ""));
1361
- const finishReason = _optionalChain([json, 'optionalAccess', _74 => _74.choices, 'optionalAccess', _75 => _75[0], 'optionalAccess', _76 => _76.finish_reason]);
1362
- let toolCalls;
1363
- if (_optionalChain([message, 'optionalAccess', _77 => _77.tool_calls]) && Array.isArray(message.tool_calls)) {
1364
- toolCalls = message.tool_calls.map((tc) => {
1365
- const rawArgs = _optionalChain([tc, 'access', _78 => _78.function, 'optionalAccess', _79 => _79.arguments]);
1366
- return {
1367
- id: tc.id,
1368
- type: "function",
1369
- function: {
1370
- name: _nullishCoalesce(_optionalChain([tc, 'access', _80 => _80.function, 'optionalAccess', _81 => _81.name]), () => ( "")),
1371
- arguments: _nullishCoalesce(rawArgs, () => ( "{}"))
1372
- }
1373
- };
1374
- });
1375
- }
1376
- let usage;
1377
- if (_optionalChain([json, 'optionalAccess', _82 => _82.usage])) {
1378
- usage = {
1379
- promptTokens: _nullishCoalesce(json.usage.prompt_tokens, () => ( 0)),
1380
- completionTokens: _nullishCoalesce(json.usage.completion_tokens, () => ( 0)),
1381
- totalTokens: _nullishCoalesce(json.usage.total_tokens, () => ( 0))
1382
- };
1383
- }
1384
- return {
1385
- id: _nullishCoalesce(json.id, () => ( "llmgateway-response")),
1386
- created: _nullishCoalesce(json.created, () => ( Date.now())),
1387
- content: text,
1388
- toolCalls,
1389
- finishReason,
1390
- usage,
1391
- raw: json
1392
- };
1393
- }
1394
- async buildFriendlyError(response) {
1395
- const status = response.status;
1396
- let errorDetail = "";
1397
- try {
1398
- const body = await response.json();
1399
- errorDetail = _optionalChain([body, 'optionalAccess', _83 => _83.error, 'optionalAccess', _84 => _84.message]) || _optionalChain([body, 'optionalAccess', _85 => _85.error]) || _optionalChain([body, 'optionalAccess', _86 => _86.message]) || "";
1400
- if (typeof errorDetail === "object") {
1401
- errorDetail = JSON.stringify(errorDetail);
1402
- }
1403
- } catch (e14) {
1404
- try {
1405
- errorDetail = await response.text();
1406
- } catch (e15) {
1407
- }
1408
- }
1409
- const friendlyMessage = FRIENDLY_ERRORS[status];
1410
- if (friendlyMessage) {
1411
- return errorDetail ? `${friendlyMessage}
1412
- ${errorDetail}` : friendlyMessage;
1413
- }
1414
- if (status >= 500) {
1415
- const base = "The LLM Gateway service is temporarily unavailable. Please try again later.";
1416
- return errorDetail ? `${base}
1417
- (${status}: ${errorDetail})` : base;
1418
- }
1419
- if (status >= 400) {
1420
- const base = "The request could not be processed.";
1421
- return errorDetail ? `${base} (${status}: ${errorDetail})` : `${base} (HTTP ${status}) Please try again or adjust your prompt.`;
1422
- }
1423
- return errorDetail ? `An unexpected error occurred: ${errorDetail}` : "An unexpected error occurred. Please try again.";
1424
- }
1425
- isNonRetryableError(error) {
1426
- const message = error.message.toLowerCase();
1427
- if (message.includes("cancelled") || message.includes("aborted")) {
1428
- return true;
1429
- }
1430
- if (message.includes("authentication") || message.includes("api key")) {
1431
- return true;
1432
- }
1433
- if (message.includes("payment") || message.includes("access denied")) {
1434
- return true;
1435
- }
1436
- if (message.includes("not found")) {
1437
- return true;
1438
- }
1439
- return false;
1440
- }
1441
- combineSignals(signal1, signal2) {
1442
- const controller = new AbortController();
1443
- const abort = () => controller.abort();
1444
- signal1.addEventListener("abort", abort);
1445
- signal2.addEventListener("abort", abort);
1446
- if (signal1.aborted || signal2.aborted) {
1447
- controller.abort();
1448
- }
1449
- return controller.signal;
1450
- }
1451
- sleep(ms) {
1452
- return new Promise((resolve) => setTimeout(resolve, ms));
1453
- }
1454
- };
1455
-
1456
- // src/providers/LLMGatewayProvider.ts
1457
- var LLMGatewayProvider = class {
1458
- constructor(config, networkSettings) {
1459
- this.client = new LLMGatewayClient(config, networkSettings);
1460
- this.model = config.model;
1461
- }
1462
- getName() {
1463
- return "llmgateway";
1464
- }
1465
- setModel(model) {
1466
- this.model = model;
1467
- this.client.setDefaultModel(model);
1468
- }
1469
- async listModels() {
1470
- return [
1471
- "gpt-4o",
1472
- "gpt-4o-mini",
1473
- "gpt-4-turbo",
1474
- "claude-3-5-sonnet-20241022",
1475
- "claude-3-5-haiku-20241022",
1476
- "gemini-1.5-pro",
1477
- "gemini-1.5-flash"
1478
- ];
1479
- }
1480
- async isAvailable() {
1481
- return true;
1482
- }
1483
- async complete(request) {
1484
- return this.client.complete(request);
1485
- }
1486
- };
1487
-
1488
- // src/providers/azure/tokenManager.ts
1489
- var EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
1490
- var IMDS_ENDPOINT = "http://169.254.169.254/metadata/identity/oauth2/token";
1491
- var COGNITIVE_SCOPE = "https://cognitiveservices.azure.com/.default";
1492
- var AzureTokenManager = class {
1493
- constructor() {
1494
- this.cache = null;
1495
- }
1496
- async getToken(request) {
1497
- if (request.authMethod === "api-key") {
1498
- if (!request.apiKey) {
1499
- throw new Error("API key is required for api-key authentication.");
1500
- }
1501
- return request.apiKey;
1502
- }
1503
- if (this.cache && !this.isTokenExpired()) {
1504
- return this.cache.token;
1505
- }
1506
- if (request.authMethod === "entra-id") {
1507
- return this.acquireEntraIdToken(request);
1508
- }
1509
- if (request.authMethod === "managed-identity") {
1510
- return this.acquireManagedIdentityToken();
1511
- }
1512
- throw new Error(`Unsupported auth method: ${request.authMethod}`);
1513
- }
1514
- async getAuthHeaders(request) {
1515
- if (request.authMethod === "api-key") {
1516
- const key = await this.getToken(request);
1517
- return { "api-key": key };
1518
- }
1519
- const token = await this.getToken(request);
1520
- return { Authorization: `Bearer ${token}` };
1521
- }
1522
- async acquireEntraIdToken(request) {
1523
- if (!request.tenantId) {
1524
- throw new Error("tenantId is required for Entra ID authentication.");
1525
- }
1526
- if (!request.clientId) {
1527
- throw new Error("clientId is required for Entra ID authentication.");
1528
- }
1529
- if (!request.clientSecret) {
1530
- throw new Error("clientSecret is required for Entra ID authentication.");
1531
- }
1532
- const url = `https://login.microsoftonline.com/${request.tenantId}/oauth2/v2.0/token`;
1533
- const body = new URLSearchParams({
1534
- grant_type: "client_credentials",
1535
- client_id: request.clientId,
1536
- client_secret: request.clientSecret,
1537
- scope: COGNITIVE_SCOPE
1538
- });
1539
- const response = await fetch(url, {
1540
- method: "POST",
1541
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
1542
- body: body.toString()
1543
- });
1544
- if (!response.ok) {
1545
- const error = await response.json().catch(() => ({}));
1546
- const description = error.error_description || error.error || `HTTP ${response.status}`;
1547
- throw new Error(`Entra ID authentication failed: ${description}`);
1548
- }
1549
- const data = await response.json();
1550
- this.cacheToken(data.access_token, data.expires_in);
1551
- return data.access_token;
1552
- }
1553
- async acquireManagedIdentityToken() {
1554
- const url = `${IMDS_ENDPOINT}?api-version=2018-02-01&resource=https://cognitiveservices.azure.com`;
1555
- let response;
1556
- try {
1557
- response = await fetch(url, {
1558
- headers: { Metadata: "true" }
1559
- });
1560
- } catch (e16) {
1561
- throw new Error(
1562
- "Managed Identity token acquisition failed. This auth method only works inside Azure VMs, App Service, or containers with managed identity enabled."
1563
- );
1564
- }
1565
- if (!response.ok) {
1566
- const error = await response.json().catch(() => ({}));
1567
- throw new Error(
1568
- `Managed Identity token error (${response.status}): ${error.error_description || error.error || "Unknown"}`
1569
- );
1570
- }
1571
- const data = await response.json();
1572
- this.cacheToken(data.access_token, data.expires_in);
1573
- return data.access_token;
1574
- }
1575
- cacheToken(token, expiresInSeconds) {
1576
- this.cache = {
1577
- token,
1578
- expiresAt: Date.now() + expiresInSeconds * 1e3
1579
- };
1580
- }
1581
- isTokenExpired() {
1582
- if (!this.cache) return true;
1583
- return Date.now() >= this.cache.expiresAt - EXPIRY_BUFFER_MS;
1584
- }
1585
- };
1586
-
1587
- // src/providers/AzureClient.ts
1588
- function sanitizeMessages3(messages) {
1589
- return messages.map((msg) => {
1590
- const sanitized = {
1591
- role: msg.role,
1592
- content: msg.content
1593
- };
1594
- if (msg.role === "tool" && msg.tool_call_id) {
1595
- sanitized.tool_call_id = msg.tool_call_id;
1596
- }
1597
- if (msg.role === "assistant" && _optionalChain([msg, 'access', _87 => _87.tool_calls, 'optionalAccess', _88 => _88.length])) {
1598
- sanitized.tool_calls = msg.tool_calls;
1599
- }
1600
- if (msg.name) {
1601
- sanitized.name = msg.name;
1602
- }
1603
- return sanitized;
1604
- });
1605
- }
1606
- var DEFAULT_API_VERSION = "2024-10-21";
1607
- var DEFAULT_MAX_RETRIES5 = 3;
1608
- var MAX_ALLOWED_RETRIES5 = 5;
1609
- var DEFAULT_RETRY_DELAY5 = 1e3;
1610
- var DEFAULT_TIMEOUT5 = 3e4;
1611
- var FRIENDLY_ERRORS2 = {
1612
- 400: "The request was malformed. This often happens when the context is too long. Try /undo to remove recent turns or /new to start fresh.",
1613
- 401: "Authentication failed. Please verify your Azure API key or credentials in ~/.autohand/config.json.",
1614
- 402: "Payment required. Please check your Azure subscription and billing settings.",
1615
- 403: "Access denied. Your credentials may not have permission for this Azure deployment.",
1616
- 404: "The Azure deployment was not found. Verify your resourceName and deploymentName in ~/.autohand/config.json.",
1617
- 429: "Rate limit exceeded. Please wait a moment and try again, or adjust your Azure deployment capacity.",
1618
- 500: "Azure OpenAI encountered an internal error. Please try again later.",
1619
- 502: "Azure OpenAI is temporarily unavailable. Please try again in a few moments.",
1620
- 503: "Azure OpenAI is currently overloaded. Please try again later.",
1621
- 504: "The request timed out. Azure OpenAI may be experiencing high load."
1622
- };
1623
- var AzureClient = class {
1624
- constructor(options, networkSettings) {
1625
- this.options = options;
1626
- this.tokenManager = new AzureTokenManager();
1627
- this.defaultModel = options.model;
1628
- const configuredRetries = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _89 => _89.maxRetries]), () => ( DEFAULT_MAX_RETRIES5));
1629
- this.maxRetries = Math.min(
1630
- Math.max(0, configuredRetries),
1631
- MAX_ALLOWED_RETRIES5
1632
- );
1633
- this.retryDelay = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _90 => _90.retryDelay]), () => ( DEFAULT_RETRY_DELAY5));
1634
- this.timeout = _nullishCoalesce(_optionalChain([networkSettings, 'optionalAccess', _91 => _91.timeout]), () => ( DEFAULT_TIMEOUT5));
1635
- }
1636
- setDefaultModel(model) {
1637
- this.defaultModel = model;
1638
- }
1639
- /**
1640
- * Build the full Azure OpenAI endpoint URL.
1641
- *
1642
- * If baseUrl is provided:
1643
- * {baseUrl}/chat/completions?api-version={apiVersion}
1644
- *
1645
- * If resourceName is a full URL (starts with https://):
1646
- * {origin}/openai/deployments/{deploymentName}/chat/completions?api-version={apiVersion}
1647
- * Supports all Azure endpoint domains:
1648
- * - *.openai.azure.com (Azure OpenAI)
1649
- * - *.services.ai.azure.com (Microsoft Foundry)
1650
- * - *.cognitiveservices.azure.com (Azure AI Services)
1651
- *
1652
- * Otherwise, from resourceName + deploymentName:
1653
- * https://{resourceName}.openai.azure.com/openai/deployments/{deploymentName}/chat/completions?api-version={apiVersion}
1654
- */
1655
- buildEndpointUrl() {
1656
- const apiVersion = _nullishCoalesce(this.options.apiVersion, () => ( DEFAULT_API_VERSION));
1657
- if (this.options.baseUrl) {
1658
- return `${this.options.baseUrl}/chat/completions?api-version=${apiVersion}`;
1659
- }
1660
- const { resourceName, deploymentName } = this.options;
1661
- if (!resourceName || !deploymentName) {
1662
- throw new Error(
1663
- "Azure OpenAI requires either baseUrl or both resourceName and deploymentName in ~/.autohand/config.json."
1664
- );
1665
- }
1666
- if (resourceName.startsWith("http://") || resourceName.startsWith("https://")) {
1667
- try {
1668
- const parsed = new URL(resourceName);
1669
- return `${parsed.origin}/openai/deployments/${deploymentName}/chat/completions?api-version=${apiVersion}`;
1670
- } catch (e17) {
1671
- }
1672
- }
1673
- return `https://${resourceName}.openai.azure.com/openai/deployments/${deploymentName}/chat/completions?api-version=${apiVersion}`;
1674
- }
1675
- async complete(request) {
1676
- const payload = {
1677
- messages: sanitizeMessages3(request.messages),
1678
- temperature: _nullishCoalesce(request.temperature, () => ( 0.2)),
1679
- max_tokens: _nullishCoalesce(request.maxTokens, () => ( 16e3)),
1680
- stream: _nullishCoalesce(request.stream, () => ( false))
1681
- };
1682
- if (request.tools && request.tools.length > 0) {
1683
- payload.tools = request.tools.map((tool) => ({
1684
- type: "function",
1685
- function: {
1686
- name: tool.name,
1687
- description: tool.description,
1688
- parameters: _nullishCoalesce(tool.parameters, () => ( { type: "object", properties: {} }))
1689
- }
1690
- }));
1691
- if (request.toolChoice) {
1692
- payload.tool_choice = request.toolChoice;
1693
- }
1694
- }
1695
- const authHeaders = await this.tokenManager.getAuthHeaders({
1696
- authMethod: this.options.authMethod,
1697
- apiKey: this.options.apiKey,
1698
- tenantId: this.options.tenantId,
1699
- clientId: this.options.clientId,
1700
- clientSecret: this.options.clientSecret
1701
- });
1702
- const headers = {
1703
- "Content-Type": "application/json",
1704
- ...authHeaders
1705
- };
1706
- const payloadJson = JSON.stringify(payload);
1707
- const payloadSizeBytes = payloadJson.length;
1708
- const maxPayloadSize = 5 * 1024 * 1024;
1709
- if (payloadSizeBytes > maxPayloadSize) {
1710
- const sizeMB = (payloadSizeBytes / (1024 * 1024)).toFixed(2);
1711
- throw new Error(
1712
- `Request payload too large (${sizeMB}MB). This usually happens when the conversation history grows too long. Try using /undo to remove recent turns or /new to start fresh.`
1713
- );
1714
- }
1715
- let lastError = null;
1716
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
1717
- try {
1718
- const response = await this.makeRequest(
1719
- payload,
1720
- headers,
1721
- request.signal,
1722
- payloadJson
1723
- );
1724
- return response;
1725
- } catch (error) {
1726
- lastError = error;
1727
- if (this.isNonRetryableError(error)) {
1728
- throw error;
1729
- }
1730
- if (attempt < this.maxRetries) {
1731
- const delay = this.retryDelay * Math.pow(2, attempt);
1732
- await this.sleep(delay);
1733
- }
1734
- }
1735
- }
1736
- throw _nullishCoalesce(lastError, () => ( new Error(
1737
- "Failed to communicate with Azure OpenAI. Please try again."
1738
- )));
1739
- }
1740
- async makeRequest(payload, headers, signal, preSerializedBody) {
1741
- let response;
1742
- const url = this.buildEndpointUrl();
1743
- try {
1744
- const timeoutController = new AbortController();
1745
- const timeoutId = setTimeout(
1746
- () => timeoutController.abort(),
1747
- this.timeout
1748
- );
1749
- const combinedSignal = signal ? this.combineSignals(signal, timeoutController.signal) : timeoutController.signal;
1750
- try {
1751
- response = await fetch(url, {
1752
- method: "POST",
1753
- headers,
1754
- body: _nullishCoalesce(preSerializedBody, () => ( JSON.stringify(payload))),
1755
- signal: combinedSignal
1756
- });
1757
- } finally {
1758
- clearTimeout(timeoutId);
1759
- }
1760
- } catch (error) {
1761
- const err = error;
1762
- if (err.name === "AbortError" && _optionalChain([signal, 'optionalAccess', _92 => _92.aborted])) {
1763
- throw new Error("Request cancelled.");
1764
- }
1765
- if (err.name === "AbortError") {
1766
- throw new Error(
1767
- "Request timed out. Azure OpenAI may be experiencing high load."
1768
- );
1769
- }
1770
- throw new Error(
1771
- "Unable to connect to Azure OpenAI. Please check your internet connection and Azure configuration."
1772
- );
1773
- }
1774
- if (!response.ok) {
1775
- throw new Error(await this.buildFriendlyError(response));
1776
- }
1777
- const json = await response.json();
1778
- const message = _optionalChain([json, 'optionalAccess', _93 => _93.choices, 'optionalAccess', _94 => _94[0], 'optionalAccess', _95 => _95.message]);
1779
- const text = _nullishCoalesce(_optionalChain([message, 'optionalAccess', _96 => _96.content]), () => ( ""));
1780
- const finishReason = _optionalChain([json, 'optionalAccess', _97 => _97.choices, 'optionalAccess', _98 => _98[0], 'optionalAccess', _99 => _99.finish_reason]);
1781
- let toolCalls;
1782
- if (_optionalChain([message, 'optionalAccess', _100 => _100.tool_calls]) && Array.isArray(message.tool_calls)) {
1783
- toolCalls = message.tool_calls.map((tc) => {
1784
- const rawArgs = _optionalChain([tc, 'access', _101 => _101.function, 'optionalAccess', _102 => _102.arguments]);
1785
- return {
1786
- id: tc.id,
1787
- type: "function",
1788
- function: {
1789
- name: _nullishCoalesce(_optionalChain([tc, 'access', _103 => _103.function, 'optionalAccess', _104 => _104.name]), () => ( "")),
1790
- arguments: _nullishCoalesce(rawArgs, () => ( "{}"))
1791
- }
1792
- };
1793
- });
1794
- }
1795
- let usage;
1796
- if (_optionalChain([json, 'optionalAccess', _105 => _105.usage])) {
1797
- usage = {
1798
- promptTokens: _nullishCoalesce(json.usage.prompt_tokens, () => ( 0)),
1799
- completionTokens: _nullishCoalesce(json.usage.completion_tokens, () => ( 0)),
1800
- totalTokens: _nullishCoalesce(json.usage.total_tokens, () => ( 0))
1801
- };
1802
- }
1803
- return {
1804
- id: _nullishCoalesce(json.id, () => ( "autohand-azure")),
1805
- created: _nullishCoalesce(json.created, () => ( Date.now())),
1806
- content: text,
1807
- toolCalls,
1808
- finishReason,
1809
- usage,
1810
- raw: json
1811
- };
1812
- }
1813
- async buildFriendlyError(response) {
1814
- const status = response.status;
1815
- let errorDetail = "";
1816
- try {
1817
- const body = await response.json();
1818
- errorDetail = _optionalChain([body, 'optionalAccess', _106 => _106.error, 'optionalAccess', _107 => _107.message]) || _optionalChain([body, 'optionalAccess', _108 => _108.error]) || _optionalChain([body, 'optionalAccess', _109 => _109.message]) || "";
1819
- if (typeof errorDetail === "object") {
1820
- errorDetail = JSON.stringify(errorDetail);
1821
- }
1822
- } catch (e18) {
1823
- try {
1824
- errorDetail = await response.text();
1825
- } catch (e19) {
1826
- }
1827
- }
1828
- const friendlyMessage = FRIENDLY_ERRORS2[status];
1829
- if (friendlyMessage) {
1830
- return errorDetail ? `${friendlyMessage}
1831
- ${errorDetail}` : friendlyMessage;
1832
- }
1833
- if (status >= 500) {
1834
- const base = "Azure OpenAI is temporarily unavailable. Please try again later.";
1835
- return errorDetail ? `${base}
1836
- (${status}: ${errorDetail})` : base;
1837
- }
1838
- if (status >= 400) {
1839
- const base = "The request could not be processed by Azure OpenAI.";
1840
- return errorDetail ? `${base} (${status}: ${errorDetail})` : `${base} (HTTP ${status}) Please try again or adjust your prompt.`;
1841
- }
1842
- return errorDetail ? `An unexpected Azure OpenAI error occurred: ${errorDetail}` : "An unexpected Azure OpenAI error occurred. Please try again.";
1843
- }
1844
- isNonRetryableError(error) {
1845
- const message = error.message.toLowerCase();
1846
- if (message.includes("cancelled") || message.includes("aborted")) {
1847
- return true;
1848
- }
1849
- if (message.includes("authentication") || message.includes("api key")) {
1850
- return true;
1851
- }
1852
- if (message.includes("payment") || message.includes("access denied")) {
1853
- return true;
1854
- }
1855
- if (message.includes("not found")) {
1856
- return true;
1857
- }
1858
- return false;
1859
- }
1860
- combineSignals(signal1, signal2) {
1861
- const controller = new AbortController();
1862
- const abort = () => controller.abort();
1863
- signal1.addEventListener("abort", abort);
1864
- signal2.addEventListener("abort", abort);
1865
- if (signal1.aborted || signal2.aborted) {
1866
- controller.abort();
1867
- }
1868
- return controller.signal;
1869
- }
1870
- sleep(ms) {
1871
- return new Promise((resolve) => setTimeout(resolve, ms));
1872
- }
1873
- };
1874
-
1875
- // src/providers/AzureProvider.ts
1876
- var AzureProvider = class {
1877
- constructor(config, networkSettings) {
1878
- this.client = new AzureClient(
1879
- {
1880
- model: config.model,
1881
- resourceName: config.resourceName,
1882
- deploymentName: config.deploymentName,
1883
- baseUrl: config.baseUrl,
1884
- apiVersion: config.apiVersion,
1885
- apiKey: config.apiKey,
1886
- authMethod: _nullishCoalesce(config.authMethod, () => ( "api-key")),
1887
- tenantId: config.tenantId,
1888
- clientId: config.clientId,
1889
- clientSecret: config.clientSecret
1890
- },
1891
- networkSettings
1892
- );
1893
- this.model = config.model;
1894
- }
1895
- getName() {
1896
- return "azure";
1897
- }
1898
- setModel(model) {
1899
- this.model = model;
1900
- this.client.setDefaultModel(model);
1901
- }
1902
- async listModels() {
1903
- return ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo"];
1904
- }
1905
- async isAvailable() {
1906
- return true;
1907
- }
1908
- async complete(request) {
1909
- return this.client.complete(request);
1910
- }
1911
- };
1912
-
1913
- // src/providers/ProviderFactory.ts
1914
- var ProviderNotConfiguredError = class extends Error {
1915
- constructor(providerName) {
1916
- super(`PROVIDER_NOT_CONFIGURED:${providerName}`);
1917
- this.providerName = providerName;
1918
- this.name = "ProviderNotConfiguredError";
1919
- }
1920
- };
1921
- var UnconfiguredProvider = class {
1922
- constructor(providerName) {
1923
- this.providerName = providerName;
1924
- }
1925
- getName() {
1926
- return "unconfigured";
1927
- }
1928
- async complete(_request) {
1929
- throw new ProviderNotConfiguredError(this.providerName);
1930
- }
1931
- async listModels() {
1932
- return [];
1933
- }
1934
- async isAvailable() {
1935
- return false;
1936
- }
1937
- setModel(_model) {
1938
- }
1939
- };
1940
- var ProviderFactory = class {
1941
- /**
1942
- * Create an LLM provider based on configuration.
1943
- * Returns an UnconfiguredProvider if the selected provider is not configured,
1944
- * allowing the agent to handle it gracefully instead of crashing.
1945
- */
1946
- static create(config) {
1947
- const providerName = config.provider || "openrouter";
1948
- switch (providerName) {
1949
- case "ollama":
1950
- if (!config.ollama) {
1951
- return new UnconfiguredProvider("ollama");
1952
- }
1953
- return new OllamaProvider(config.ollama, config.network);
1954
- case "openai":
1955
- if (!config.openai) {
1956
- return new UnconfiguredProvider("openai");
1957
- }
1958
- return new OpenAIProvider(config.openai);
1959
- case "llamacpp":
1960
- if (!config.llamacpp) {
1961
- return new UnconfiguredProvider("llamacpp");
1962
- }
1963
- return new LlamaCppProvider(config.llamacpp);
1964
- case "mlx":
1965
- if (!config.mlx) {
1966
- return new UnconfiguredProvider("mlx");
1967
- }
1968
- return new MLXProvider(config.mlx, config.network);
1969
- case "llmgateway":
1970
- if (!config.llmgateway) {
1971
- return new UnconfiguredProvider("llmgateway");
1972
- }
1973
- return new LLMGatewayProvider(config.llmgateway, config.network);
1974
- case "azure":
1975
- if (!config.azure) {
1976
- return new UnconfiguredProvider("azure");
1977
- }
1978
- return new AzureProvider(config.azure, config.network);
1979
- case "openrouter":
1980
- default:
1981
- if (!config.openrouter) {
1982
- return new UnconfiguredProvider("openrouter");
1983
- }
1984
- return new OpenRouterProvider(config.openrouter);
1985
- }
1986
- }
1987
- /**
1988
- * Get all available provider names.
1989
- * MLX is only included on Apple Silicon (macOS + arm64).
1990
- */
1991
- static getProviderNames() {
1992
- const providers = ["openrouter", "ollama", "openai", "llamacpp", "llmgateway", "azure"];
1993
- if (isMLXSupported()) {
1994
- providers.push("mlx");
1995
- }
1996
- return providers;
1997
- }
1998
- /**
1999
- * Check if a provider name is valid.
2000
- * Note: This checks if the name is a valid provider type, not if it's available on this platform.
2001
- * MLX is always a valid provider name, but may not be available on non-Apple Silicon systems.
2002
- */
2003
- static isValidProvider(name) {
2004
- const allProviders = ["openrouter", "ollama", "openai", "llamacpp", "mlx", "llmgateway", "azure"];
2005
- return allProviders.includes(name);
2006
- }
2007
- };
2008
-
2009
-
2010
-
2011
-
2012
-
2013
-
2014
- exports.ApiError = ApiError; exports.classifyApiError = classifyApiError; exports.ProviderNotConfiguredError = ProviderNotConfiguredError; exports.ProviderFactory = ProviderFactory;
2015
- /**
2016
- * @license
2017
- * Copyright 2025 Autohand AI LLC
2018
- * SPDX-License-Identifier: Apache-2.0
2019
- *
2020
- * Centralized API error classification.
2021
- *
2022
- * Every provider (OpenRouter, Azure, MLX, Ollama, LLMGateway) and every
2023
- * consumer (agent.ts, RPC adapter, ACP adapter) delegates to this module
2024
- * so error handling logic lives in one place.
2025
- */
2026
- /**
2027
- * @license
2028
- * Copyright 2025 Autohand AI LLC
2029
- * SPDX-License-Identifier: Apache-2.0
2030
- */