@shareai-lab/kode 2.0.1 → 2.0.3

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 (343) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +649 -25
  3. package/README.zh-CN.md +579 -0
  4. package/cli-acp.js +3 -17
  5. package/cli.js +5 -7
  6. package/dist/chunks/Doctor-M3J7GRTJ.js +12 -0
  7. package/dist/chunks/LogList-ISWZ6DDD.js +121 -0
  8. package/dist/chunks/LogList-ISWZ6DDD.js.map +7 -0
  9. package/dist/chunks/REPL-RQ6LO6S7.js +56 -0
  10. package/dist/chunks/ResumeConversation-6DMVBEGH.js +56 -0
  11. package/dist/chunks/agentLoader-FCRG3TFJ.js +31 -0
  12. package/dist/{agentsValidate-7LH4HTNR.js → chunks/agentsValidate-PEWMYN4Q.js} +97 -69
  13. package/dist/chunks/agentsValidate-PEWMYN4Q.js.map +7 -0
  14. package/dist/{ask-3NHFFUQG.js → chunks/ask-D7SOHJ6Z.js} +36 -44
  15. package/dist/chunks/ask-D7SOHJ6Z.js.map +7 -0
  16. package/dist/chunks/autoUpdater-CNESBOKO.js +19 -0
  17. package/dist/{chunk-AFFSCMYS.js → chunks/chunk-2JN5MY67.js} +12 -14
  18. package/dist/chunks/chunk-2JN5MY67.js.map +7 -0
  19. package/dist/chunks/chunk-2QONJ5MG.js +14 -0
  20. package/dist/chunks/chunk-2QONJ5MG.js.map +7 -0
  21. package/dist/chunks/chunk-2WEXPKHH.js +903 -0
  22. package/dist/chunks/chunk-2WEXPKHH.js.map +7 -0
  23. package/dist/{chunk-ARZSBOAO.js → chunks/chunk-3BYE3ME6.js} +717 -792
  24. package/dist/chunks/chunk-3BYE3ME6.js.map +7 -0
  25. package/dist/chunks/chunk-3JDNWX7W.js +1264 -0
  26. package/dist/chunks/chunk-3JDNWX7W.js.map +7 -0
  27. package/dist/chunks/chunk-3OEJVB5A.js +906 -0
  28. package/dist/chunks/chunk-3OEJVB5A.js.map +7 -0
  29. package/dist/chunks/chunk-3TNIOEBO.js +369 -0
  30. package/dist/chunks/chunk-3TNIOEBO.js.map +7 -0
  31. package/dist/chunks/chunk-4A46ZXMJ.js +67 -0
  32. package/dist/chunks/chunk-4A46ZXMJ.js.map +7 -0
  33. package/dist/{chunk-UHYRLID6.js → chunks/chunk-4ATBQOFO.js} +107 -55
  34. package/dist/chunks/chunk-4ATBQOFO.js.map +7 -0
  35. package/dist/chunks/chunk-4CRUCZR4.js +0 -0
  36. package/dist/{chunk-YC6LJCDE.js → chunks/chunk-4EO6SIQY.js} +32 -75
  37. package/dist/chunks/chunk-4EO6SIQY.js.map +7 -0
  38. package/dist/chunks/chunk-53M46S5I.js +64 -0
  39. package/dist/chunks/chunk-53M46S5I.js.map +7 -0
  40. package/dist/{chunk-JC6NCUG5.js → chunks/chunk-54KOYG5C.js} +0 -2
  41. package/dist/{chunk-EZXMVTDU.js → chunks/chunk-6BAS4WY6.js} +29 -45
  42. package/dist/chunks/chunk-6BAS4WY6.js.map +7 -0
  43. package/dist/{chunk-3IN27HA5.js → chunks/chunk-6KRRFSDN.js} +4 -6
  44. package/dist/chunks/chunk-6KRRFSDN.js.map +7 -0
  45. package/dist/chunks/chunk-6LJNZK4K.js +39 -0
  46. package/dist/chunks/chunk-6LJNZK4K.js.map +7 -0
  47. package/dist/chunks/chunk-6ZWEOSEI.js +666 -0
  48. package/dist/chunks/chunk-6ZWEOSEI.js.map +7 -0
  49. package/dist/chunks/chunk-77XDJMBP.js +3326 -0
  50. package/dist/chunks/chunk-77XDJMBP.js.map +7 -0
  51. package/dist/chunks/chunk-7RRW4NTB.js +6454 -0
  52. package/dist/chunks/chunk-7RRW4NTB.js.map +7 -0
  53. package/dist/chunks/chunk-7X3TW4JB.js +4520 -0
  54. package/dist/chunks/chunk-7X3TW4JB.js.map +7 -0
  55. package/dist/chunks/chunk-B3MW3YGY.js +1409 -0
  56. package/dist/chunks/chunk-B3MW3YGY.js.map +7 -0
  57. package/dist/chunks/chunk-BBJFHTBC.js +28 -0
  58. package/dist/chunks/chunk-BBJFHTBC.js.map +7 -0
  59. package/dist/chunks/chunk-BHDHXOXB.js +24 -0
  60. package/dist/chunks/chunk-BHDHXOXB.js.map +7 -0
  61. package/dist/{chunk-73WGVYLQ.js → chunks/chunk-BTA7SZ26.js} +152 -223
  62. package/dist/chunks/chunk-BTA7SZ26.js.map +7 -0
  63. package/dist/chunks/chunk-CDGRYGPZ.js +103 -0
  64. package/dist/chunks/chunk-CDGRYGPZ.js.map +7 -0
  65. package/dist/{chunk-S6HRABTA.js → chunks/chunk-CP6E5UG6.js} +1 -4
  66. package/dist/chunks/chunk-CP6E5UG6.js.map +7 -0
  67. package/dist/{chunk-QVLYOPO5.js → chunks/chunk-DQ4JHXMT.js} +462 -424
  68. package/dist/chunks/chunk-DQ4JHXMT.js.map +7 -0
  69. package/dist/chunks/chunk-DXD76CMV.js +208 -0
  70. package/dist/chunks/chunk-DXD76CMV.js.map +7 -0
  71. package/dist/chunks/chunk-GCQCAXJZ.js +0 -0
  72. package/dist/chunks/chunk-GELCZWMB.js +42 -0
  73. package/dist/chunks/chunk-GELCZWMB.js.map +7 -0
  74. package/dist/{chunk-K2CWOTI2.js → chunks/chunk-HJYOH4HC.js} +23 -18
  75. package/dist/chunks/chunk-HJYOH4HC.js.map +7 -0
  76. package/dist/chunks/chunk-HPYNW6TT.js +744 -0
  77. package/dist/chunks/chunk-HPYNW6TT.js.map +7 -0
  78. package/dist/{chunk-RZWOUA25.js → chunks/chunk-HRJ3ICQK.js} +59 -55
  79. package/dist/chunks/chunk-HRJ3ICQK.js.map +7 -0
  80. package/dist/{chunk-DZE5YA7L.js → chunks/chunk-IFCIADS3.js} +571 -573
  81. package/dist/chunks/chunk-IFCIADS3.js.map +7 -0
  82. package/dist/chunks/chunk-IN7XZ7BC.js +27 -0
  83. package/dist/chunks/chunk-IN7XZ7BC.js.map +7 -0
  84. package/dist/chunks/chunk-L7P4M4KW.js +193 -0
  85. package/dist/chunks/chunk-L7P4M4KW.js.map +7 -0
  86. package/dist/chunks/chunk-LB6TCPDI.js +0 -0
  87. package/dist/{chunk-3RUXVV4S.js → chunks/chunk-LOCXPQNJ.js} +1 -4
  88. package/dist/{chunk-3RUXVV4S.js.map → chunks/chunk-LOCXPQNJ.js.map} +2 -2
  89. package/dist/{chunk-7M2YN6TU.js → chunks/chunk-LOD5ZHCI.js} +213 -208
  90. package/dist/chunks/chunk-LOD5ZHCI.js.map +7 -0
  91. package/dist/{chunk-S3J2TLV6.js → chunks/chunk-M7P3QNRU.js} +1 -4
  92. package/dist/{chunk-S3J2TLV6.js.map → chunks/chunk-M7P3QNRU.js.map} +2 -2
  93. package/dist/chunks/chunk-PPHLQVL7.js +4234 -0
  94. package/dist/chunks/chunk-PPHLQVL7.js.map +7 -0
  95. package/dist/{chunk-ABLVTESJ.js → chunks/chunk-QAXE37B5.js} +1 -4
  96. package/dist/chunks/chunk-QAXE37B5.js.map +7 -0
  97. package/dist/chunks/chunk-QHQOBUF6.js +60 -0
  98. package/dist/chunks/chunk-QHQOBUF6.js.map +7 -0
  99. package/dist/{chunk-W7GRKO7Q.js → chunks/chunk-RPJXO7GG.js} +241 -214
  100. package/dist/chunks/chunk-RPJXO7GG.js.map +7 -0
  101. package/dist/{chunk-NPFOMITO.js → chunks/chunk-SWQV4KSY.js} +1 -4
  102. package/dist/{chunk-NPFOMITO.js.map → chunks/chunk-SWQV4KSY.js.map} +2 -2
  103. package/dist/chunks/chunk-SZLAPULP.js +28 -0
  104. package/dist/chunks/chunk-SZLAPULP.js.map +7 -0
  105. package/dist/{chunk-7U7L4NMD.js → chunks/chunk-T7RB5V5J.js} +23 -25
  106. package/dist/chunks/chunk-T7RB5V5J.js.map +7 -0
  107. package/dist/{chunk-HN4E4UUQ.js → chunks/chunk-TI2CTTMA.js} +25 -17
  108. package/dist/chunks/chunk-TI2CTTMA.js.map +7 -0
  109. package/dist/{chunk-ZVDRDPII.js → chunks/chunk-TNGVRTO5.js} +45 -20
  110. package/dist/chunks/chunk-TNGVRTO5.js.map +7 -0
  111. package/dist/chunks/chunk-TNWB3U5Y.js +2077 -0
  112. package/dist/chunks/chunk-TNWB3U5Y.js.map +7 -0
  113. package/dist/chunks/chunk-U2IHWPCU.js +12 -0
  114. package/dist/chunks/chunk-U2IHWPCU.js.map +7 -0
  115. package/dist/{chunk-KAA5BGMQ.js → chunks/chunk-UNOY3VJ2.js} +1 -4
  116. package/dist/{chunk-KAA5BGMQ.js.map → chunks/chunk-UNOY3VJ2.js.map} +2 -2
  117. package/dist/{chunk-MWRSY4X6.js → chunks/chunk-UVDJL6ZZ.js} +97 -58
  118. package/dist/chunks/chunk-UVDJL6ZZ.js.map +7 -0
  119. package/dist/chunks/chunk-VNCW4C2Z.js +13452 -0
  120. package/dist/chunks/chunk-VNCW4C2Z.js.map +7 -0
  121. package/dist/chunks/chunk-W5EGGA44.js +15 -0
  122. package/dist/chunks/chunk-W5EGGA44.js.map +7 -0
  123. package/dist/chunks/chunk-XR2W3MAM.js +1533 -0
  124. package/dist/chunks/chunk-XR2W3MAM.js.map +7 -0
  125. package/dist/{chunk-STSX7GIX.js → chunks/chunk-YIO5EBMQ.js} +423 -377
  126. package/dist/chunks/chunk-YIO5EBMQ.js.map +7 -0
  127. package/dist/chunks/chunk-ZBVLKZ5V.js +1062 -0
  128. package/dist/chunks/chunk-ZBVLKZ5V.js.map +7 -0
  129. package/dist/{chunk-E6YNABER.js → chunks/chunk-ZCLTZIVP.js} +1 -4
  130. package/dist/chunks/chunk-ZCLTZIVP.js.map +7 -0
  131. package/dist/chunks/client-SILZNM5N.js +42 -0
  132. package/dist/{config-RUSD6G5Y.js → chunks/config-25HRTPSP.js} +48 -10
  133. package/dist/chunks/cost-tracker-Z2UZT2J5.js +28 -0
  134. package/dist/{customCommands-TOIJFZAL.js → chunks/customCommands-TYMYZRG5.js} +11 -8
  135. package/dist/chunks/engine-MRVF6FK6.js +39 -0
  136. package/dist/{env-XGKBLU3D.js → chunks/env-TJ5NOBEB.js} +7 -5
  137. package/dist/{kodeAgentSessionId-X6XWQW7B.js → chunks/kodeAgentSessionId-VTNISJ2L.js} +2 -4
  138. package/dist/chunks/kodeAgentSessionLoad-YB2RKBGJ.js +15 -0
  139. package/dist/chunks/kodeAgentSessionResume-DZSIVKVA.js +13 -0
  140. package/dist/chunks/kodeAgentStreamJson-X5PLS2S6.js +11 -0
  141. package/dist/{kodeAgentStreamJsonSession-UGEZJJEB.js → chunks/kodeAgentStreamJsonSession-RDXM4XYF.js} +38 -24
  142. package/dist/chunks/kodeAgentStreamJsonSession-RDXM4XYF.js.map +7 -0
  143. package/dist/{chunk-4RTX4AG4.js → chunks/kodeAgentStructuredStdio-SVGDSB4P.js} +14 -9
  144. package/dist/chunks/kodeAgentStructuredStdio-SVGDSB4P.js.map +7 -0
  145. package/dist/{kodeHooks-QWM36A3D.js → chunks/kodeHooks-RVKYRJHG.js} +11 -9
  146. package/dist/{llm-ZUQC4WYM.js → chunks/llm-62N6T5ZT.js} +1734 -1526
  147. package/dist/chunks/llm-62N6T5ZT.js.map +7 -0
  148. package/dist/chunks/llmLazy-ZUSSE3ZA.js +13 -0
  149. package/dist/{mentionProcessor-EE3XFHCJ.js → chunks/mentionProcessor-RJW5UPJD.js} +46 -16
  150. package/dist/chunks/mentionProcessor-RJW5UPJD.js.map +7 -0
  151. package/dist/{messages-EOYQKPGM.js → chunks/messages-EEWWLPHN.js} +2 -6
  152. package/dist/chunks/model-5TIEKQPD.js +37 -0
  153. package/dist/{openai-RRCWW33N.js → chunks/openai-XXK3YZG4.js} +13 -10
  154. package/dist/{outputStyles-62Q3VH2J.js → chunks/outputStyles-FAJTXN2A.js} +6 -9
  155. package/dist/chunks/permissions-HO7INPWM.js +27 -0
  156. package/dist/{pluginRuntime-6ETCZ2LL.js → chunks/pluginRuntime-C7K5ULK2.js} +31 -48
  157. package/dist/chunks/pluginRuntime-C7K5ULK2.js.map +7 -0
  158. package/dist/chunks/pluginValidation-DAM7WRTC.js +20 -0
  159. package/dist/chunks/registry-XYJXMOA5.js +60 -0
  160. package/dist/chunks/responsesStreaming-JNGE2P3D.js +8 -0
  161. package/dist/chunks/runNonTextPrintMode-SVBLCZQX.js +577 -0
  162. package/dist/chunks/runNonTextPrintMode-SVBLCZQX.js.map +7 -0
  163. package/dist/chunks/server-REXXF5IK.js +46 -0
  164. package/dist/{skillMarketplace-3RXQBVOL.js → chunks/skillMarketplace-N4HVHNST.js} +8 -6
  165. package/dist/chunks/src-OROQIWP3.js +44 -0
  166. package/dist/chunks/src-QXLGGMUW.js +1647 -0
  167. package/dist/chunks/src-QXLGGMUW.js.map +7 -0
  168. package/dist/{cli-DOPVY2CW.js → chunks/src-SSDT6MVP.js} +2659 -3384
  169. package/dist/chunks/src-SSDT6MVP.js.map +7 -0
  170. package/dist/chunks/theme-YBJUIMWK.js +10 -0
  171. package/dist/{toolPermissionContext-65L65VEZ.js → chunks/toolPermissionContext-MOCTRR7N.js} +2 -4
  172. package/dist/chunks/toolPermissionSettings-EV2EJAXL.js +18 -0
  173. package/dist/chunks/toolPermissionSettings-EV2EJAXL.js.map +7 -0
  174. package/dist/chunks/uuid-6577SO6X.js +7 -0
  175. package/dist/chunks/uuid-6577SO6X.js.map +7 -0
  176. package/dist/chunks/webOnlyMode-ALXX7UQY.js +66 -0
  177. package/dist/chunks/webOnlyMode-ALXX7UQY.js.map +7 -0
  178. package/dist/entrypoints/cli.js +10 -0
  179. package/dist/entrypoints/cli.js.map +7 -0
  180. package/dist/entrypoints/daemon.js +10 -0
  181. package/dist/entrypoints/daemon.js.map +7 -0
  182. package/dist/entrypoints/mcp.js +71 -0
  183. package/dist/entrypoints/mcp.js.map +7 -0
  184. package/dist/index.js +6 -7
  185. package/dist/index.js.map +3 -3
  186. package/dist/sdk/client.cjs +391 -0
  187. package/dist/sdk/client.cjs.map +7 -0
  188. package/dist/sdk/client.js +364 -0
  189. package/dist/sdk/client.js.map +7 -0
  190. package/dist/sdk/core.cjs +19932 -0
  191. package/dist/sdk/core.cjs.map +7 -0
  192. package/dist/sdk/core.js +19893 -0
  193. package/dist/sdk/core.js.map +7 -0
  194. package/dist/sdk/daemon-client.cjs +257 -0
  195. package/dist/sdk/daemon-client.cjs.map +7 -0
  196. package/dist/sdk/daemon-client.js +221 -0
  197. package/dist/sdk/daemon-client.js.map +7 -0
  198. package/dist/sdk/protocol.cjs +170 -0
  199. package/dist/sdk/protocol.cjs.map +7 -0
  200. package/dist/sdk/protocol.js +140 -0
  201. package/dist/sdk/protocol.js.map +7 -0
  202. package/dist/sdk/runtime-node.cjs +236 -0
  203. package/dist/sdk/runtime-node.cjs.map +7 -0
  204. package/dist/sdk/runtime-node.js +222 -0
  205. package/dist/sdk/runtime-node.js.map +7 -0
  206. package/dist/sdk/runtime.cjs +17 -0
  207. package/dist/sdk/runtime.cjs.map +7 -0
  208. package/dist/sdk/runtime.js +0 -0
  209. package/dist/sdk/runtime.js.map +7 -0
  210. package/dist/sdk/tools.cjs +30300 -0
  211. package/dist/sdk/tools.cjs.map +7 -0
  212. package/dist/sdk/tools.js +30282 -0
  213. package/dist/sdk/tools.js.map +7 -0
  214. package/dist/webui/assets/index-5hlfByVS.css +1 -0
  215. package/dist/webui/assets/index-BR9lm1lA.js +82 -0
  216. package/dist/webui/index.html +28 -0
  217. package/package.json +93 -22
  218. package/scripts/binary-utils.cjs +12 -4
  219. package/scripts/cli-acp-wrapper.cjs +3 -17
  220. package/scripts/cli-wrapper.cjs +5 -7
  221. package/scripts/postinstall.js +8 -4
  222. package/dist/REPL-CW7AYLVL.js +0 -42
  223. package/dist/acp-VEPJ74LT.js +0 -1357
  224. package/dist/acp-VEPJ74LT.js.map +0 -7
  225. package/dist/agentsValidate-7LH4HTNR.js.map +0 -7
  226. package/dist/ask-3NHFFUQG.js.map +0 -7
  227. package/dist/autoUpdater-ITPIHCOI.js +0 -17
  228. package/dist/chunk-3IN27HA5.js.map +0 -7
  229. package/dist/chunk-4FX3IVPT.js +0 -164
  230. package/dist/chunk-4FX3IVPT.js.map +0 -7
  231. package/dist/chunk-4RTX4AG4.js.map +0 -7
  232. package/dist/chunk-5PDP7R6N.js +0 -515
  233. package/dist/chunk-5PDP7R6N.js.map +0 -7
  234. package/dist/chunk-73WGVYLQ.js.map +0 -7
  235. package/dist/chunk-7M2YN6TU.js.map +0 -7
  236. package/dist/chunk-7U7L4NMD.js.map +0 -7
  237. package/dist/chunk-ABLVTESJ.js.map +0 -7
  238. package/dist/chunk-AFFSCMYS.js.map +0 -7
  239. package/dist/chunk-ARZSBOAO.js.map +0 -7
  240. package/dist/chunk-CIG63V4E.js +0 -72
  241. package/dist/chunk-CIG63V4E.js.map +0 -7
  242. package/dist/chunk-CM3EGTG6.js +0 -1609
  243. package/dist/chunk-CM3EGTG6.js.map +0 -7
  244. package/dist/chunk-DZE5YA7L.js.map +0 -7
  245. package/dist/chunk-E6YNABER.js.map +0 -7
  246. package/dist/chunk-EZXMVTDU.js.map +0 -7
  247. package/dist/chunk-F2SJXUDI.js +0 -148
  248. package/dist/chunk-F2SJXUDI.js.map +0 -7
  249. package/dist/chunk-FC5ZCKBI.js +0 -30167
  250. package/dist/chunk-FC5ZCKBI.js.map +0 -7
  251. package/dist/chunk-HCBELH4J.js +0 -145
  252. package/dist/chunk-HCBELH4J.js.map +0 -7
  253. package/dist/chunk-HN4E4UUQ.js.map +0 -7
  254. package/dist/chunk-IZVMU4S2.js +0 -654
  255. package/dist/chunk-IZVMU4S2.js.map +0 -7
  256. package/dist/chunk-K2CWOTI2.js.map +0 -7
  257. package/dist/chunk-LC4TVOCZ.js +0 -835
  258. package/dist/chunk-LC4TVOCZ.js.map +0 -7
  259. package/dist/chunk-MIW7N2MY.js +0 -2613
  260. package/dist/chunk-MIW7N2MY.js.map +0 -7
  261. package/dist/chunk-MWRSY4X6.js.map +0 -7
  262. package/dist/chunk-ND3XWFO6.js +0 -34
  263. package/dist/chunk-ND3XWFO6.js.map +0 -7
  264. package/dist/chunk-QVLYOPO5.js.map +0 -7
  265. package/dist/chunk-RZWOUA25.js.map +0 -7
  266. package/dist/chunk-S6HRABTA.js.map +0 -7
  267. package/dist/chunk-STSX7GIX.js.map +0 -7
  268. package/dist/chunk-UHYRLID6.js.map +0 -7
  269. package/dist/chunk-UKHTVRJM.js +0 -47
  270. package/dist/chunk-UKHTVRJM.js.map +0 -7
  271. package/dist/chunk-UYXEDKOZ.js +0 -24
  272. package/dist/chunk-UYXEDKOZ.js.map +0 -7
  273. package/dist/chunk-W7GRKO7Q.js.map +0 -7
  274. package/dist/chunk-WVHORZQ5.js +0 -17
  275. package/dist/chunk-WVHORZQ5.js.map +0 -7
  276. package/dist/chunk-WWUWDNWW.js +0 -49
  277. package/dist/chunk-WWUWDNWW.js.map +0 -7
  278. package/dist/chunk-YC6LJCDE.js.map +0 -7
  279. package/dist/chunk-YXYYDIMI.js +0 -2931
  280. package/dist/chunk-YXYYDIMI.js.map +0 -7
  281. package/dist/chunk-ZVDRDPII.js.map +0 -7
  282. package/dist/cli-DOPVY2CW.js.map +0 -7
  283. package/dist/commands-2BF2CJ3A.js +0 -46
  284. package/dist/context-6FXPETYH.js +0 -30
  285. package/dist/costTracker-6SL26FDB.js +0 -19
  286. package/dist/kodeAgentSessionLoad-MITZADPB.js +0 -18
  287. package/dist/kodeAgentSessionResume-GVRWB4WO.js +0 -16
  288. package/dist/kodeAgentStreamJson-NXFN7TXH.js +0 -13
  289. package/dist/kodeAgentStreamJsonSession-UGEZJJEB.js.map +0 -7
  290. package/dist/kodeAgentStructuredStdio-HGWJT7CU.js +0 -10
  291. package/dist/llm-ZUQC4WYM.js.map +0 -7
  292. package/dist/llmLazy-54QQHA54.js +0 -15
  293. package/dist/loader-FYHJQES5.js +0 -28
  294. package/dist/mcp-J332IKT3.js +0 -49
  295. package/dist/mentionProcessor-EE3XFHCJ.js.map +0 -7
  296. package/dist/model-FV3JDJKH.js +0 -30
  297. package/dist/pluginRuntime-6ETCZ2LL.js.map +0 -7
  298. package/dist/pluginValidation-I4YKUWGS.js +0 -17
  299. package/dist/prompts-ZLEKDD77.js +0 -48
  300. package/dist/query-VFRJPBGD.js +0 -50
  301. package/dist/responsesStreaming-AW344PQO.js +0 -10
  302. package/dist/ripgrep-3NTIKQYW.js +0 -17
  303. package/dist/state-P5G6CO5V.js +0 -16
  304. package/dist/theme-3LWP3BG7.js +0 -14
  305. package/dist/toolPermissionSettings-3ROBVTUK.js +0 -18
  306. package/dist/tools-RO7HSSE5.js +0 -47
  307. package/dist/userInput-JSBJRFSK.js +0 -311
  308. package/dist/userInput-JSBJRFSK.js.map +0 -7
  309. package/dist/uuid-QN2CNKKN.js +0 -9
  310. /package/dist/{REPL-CW7AYLVL.js.map → chunks/Doctor-M3J7GRTJ.js.map} +0 -0
  311. /package/dist/{autoUpdater-ITPIHCOI.js.map → chunks/REPL-RQ6LO6S7.js.map} +0 -0
  312. /package/dist/{chunk-JC6NCUG5.js.map → chunks/ResumeConversation-6DMVBEGH.js.map} +0 -0
  313. /package/dist/{commands-2BF2CJ3A.js.map → chunks/agentLoader-FCRG3TFJ.js.map} +0 -0
  314. /package/dist/{config-RUSD6G5Y.js.map → chunks/autoUpdater-CNESBOKO.js.map} +0 -0
  315. /package/dist/{context-6FXPETYH.js.map → chunks/chunk-4CRUCZR4.js.map} +0 -0
  316. /package/dist/{costTracker-6SL26FDB.js.map → chunks/chunk-54KOYG5C.js.map} +0 -0
  317. /package/dist/{customCommands-TOIJFZAL.js.map → chunks/chunk-GCQCAXJZ.js.map} +0 -0
  318. /package/dist/{env-XGKBLU3D.js.map → chunks/chunk-LB6TCPDI.js.map} +0 -0
  319. /package/dist/{kodeAgentSessionId-X6XWQW7B.js.map → chunks/client-SILZNM5N.js.map} +0 -0
  320. /package/dist/{kodeAgentSessionLoad-MITZADPB.js.map → chunks/config-25HRTPSP.js.map} +0 -0
  321. /package/dist/{kodeAgentSessionResume-GVRWB4WO.js.map → chunks/cost-tracker-Z2UZT2J5.js.map} +0 -0
  322. /package/dist/{kodeAgentStreamJson-NXFN7TXH.js.map → chunks/customCommands-TYMYZRG5.js.map} +0 -0
  323. /package/dist/{kodeAgentStructuredStdio-HGWJT7CU.js.map → chunks/engine-MRVF6FK6.js.map} +0 -0
  324. /package/dist/{kodeHooks-QWM36A3D.js.map → chunks/env-TJ5NOBEB.js.map} +0 -0
  325. /package/dist/{llmLazy-54QQHA54.js.map → chunks/kodeAgentSessionId-VTNISJ2L.js.map} +0 -0
  326. /package/dist/{loader-FYHJQES5.js.map → chunks/kodeAgentSessionLoad-YB2RKBGJ.js.map} +0 -0
  327. /package/dist/{mcp-J332IKT3.js.map → chunks/kodeAgentSessionResume-DZSIVKVA.js.map} +0 -0
  328. /package/dist/{messages-EOYQKPGM.js.map → chunks/kodeAgentStreamJson-X5PLS2S6.js.map} +0 -0
  329. /package/dist/{model-FV3JDJKH.js.map → chunks/kodeHooks-RVKYRJHG.js.map} +0 -0
  330. /package/dist/{openai-RRCWW33N.js.map → chunks/llmLazy-ZUSSE3ZA.js.map} +0 -0
  331. /package/dist/{outputStyles-62Q3VH2J.js.map → chunks/messages-EEWWLPHN.js.map} +0 -0
  332. /package/dist/{pluginValidation-I4YKUWGS.js.map → chunks/model-5TIEKQPD.js.map} +0 -0
  333. /package/dist/{prompts-ZLEKDD77.js.map → chunks/openai-XXK3YZG4.js.map} +0 -0
  334. /package/dist/{query-VFRJPBGD.js.map → chunks/outputStyles-FAJTXN2A.js.map} +0 -0
  335. /package/dist/{responsesStreaming-AW344PQO.js.map → chunks/permissions-HO7INPWM.js.map} +0 -0
  336. /package/dist/{ripgrep-3NTIKQYW.js.map → chunks/pluginValidation-DAM7WRTC.js.map} +0 -0
  337. /package/dist/{skillMarketplace-3RXQBVOL.js.map → chunks/registry-XYJXMOA5.js.map} +0 -0
  338. /package/dist/{state-P5G6CO5V.js.map → chunks/responsesStreaming-JNGE2P3D.js.map} +0 -0
  339. /package/dist/{theme-3LWP3BG7.js.map → chunks/server-REXXF5IK.js.map} +0 -0
  340. /package/dist/{toolPermissionContext-65L65VEZ.js.map → chunks/skillMarketplace-N4HVHNST.js.map} +0 -0
  341. /package/dist/{toolPermissionSettings-3ROBVTUK.js.map → chunks/src-OROQIWP3.js.map} +0 -0
  342. /package/dist/{tools-RO7HSSE5.js.map → chunks/theme-YBJUIMWK.js.map} +0 -0
  343. /package/dist/{uuid-QN2CNKKN.js.map → chunks/toolPermissionContext-MOCTRR7N.js.map} +0 -0
@@ -1,47 +1,35 @@
1
- import { createRequire as __kodeCreateRequire } from "node:module";
2
- const require = __kodeCreateRequire(import.meta.url);
3
1
  import {
4
- getToolDescription
5
- } from "./chunk-WVHORZQ5.js";
2
+ models_default
3
+ } from "./chunk-2WEXPKHH.js";
4
+ import {
5
+ addToTotalCost
6
+ } from "./chunk-6BAS4WY6.js";
6
7
  import {
7
8
  processResponsesStream
8
- } from "./chunk-HN4E4UUQ.js";
9
+ } from "./chunk-TI2CTTMA.js";
10
+ import {
11
+ getCompletionWithProfile,
12
+ getGPT5CompletionWithProfile
13
+ } from "./chunk-IFCIADS3.js";
14
+ import {
15
+ getReasoningEffort
16
+ } from "./chunk-53M46S5I.js";
9
17
  import {
10
18
  formatSystemPromptWithContext,
11
19
  generateKodeContext,
12
20
  getCLISyspromptPrefix,
13
- getReasoningEffort,
14
- models_default,
15
21
  refreshKodeContext
16
- } from "./chunk-FC5ZCKBI.js";
17
- import "./chunk-K2CWOTI2.js";
18
- import "./chunk-CM3EGTG6.js";
19
- import "./chunk-UHYRLID6.js";
20
- import "./chunk-QVLYOPO5.js";
21
- import "./chunk-ZVDRDPII.js";
22
- import "./chunk-MWRSY4X6.js";
23
- import "./chunk-KAA5BGMQ.js";
22
+ } from "./chunk-HPYNW6TT.js";
23
+ import "./chunk-LOD5ZHCI.js";
24
+ import "./chunk-GELCZWMB.js";
25
+ import "./chunk-3BYE3ME6.js";
26
+ import "./chunk-M7P3QNRU.js";
27
+ import "./chunk-SWQV4KSY.js";
24
28
  import {
25
29
  setRequestStatus
26
- } from "./chunk-3RUXVV4S.js";
27
- import "./chunk-ARZSBOAO.js";
28
- import "./chunk-NPFOMITO.js";
29
- import "./chunk-YC6LJCDE.js";
30
- import {
31
- getCompletionWithProfile,
32
- getGPT5CompletionWithProfile
33
- } from "./chunk-DZE5YA7L.js";
34
- import "./chunk-ND3XWFO6.js";
35
- import "./chunk-4FX3IVPT.js";
36
- import "./chunk-W7GRKO7Q.js";
37
- import "./chunk-AFFSCMYS.js";
38
- import "./chunk-HCBELH4J.js";
39
- import "./chunk-S6HRABTA.js";
40
- import "./chunk-7M2YN6TU.js";
41
- import "./chunk-E6YNABER.js";
42
- import "./chunk-73WGVYLQ.js";
43
- import "./chunk-UKHTVRJM.js";
44
- import "./chunk-S3J2TLV6.js";
30
+ } from "./chunk-LOCXPQNJ.js";
31
+ import "./chunk-ZCLTZIVP.js";
32
+ import "./chunk-4CRUCZR4.js";
45
33
  import {
46
34
  API_ERROR_MESSAGE_PREFIX,
47
35
  CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE,
@@ -51,20 +39,13 @@ import {
51
39
  PROMPT_TOO_LONG_ERROR_MESSAGE,
52
40
  createAssistantAPIErrorMessage,
53
41
  normalizeContentFromAPI
54
- } from "./chunk-RZWOUA25.js";
42
+ } from "./chunk-HRJ3ICQK.js";
55
43
  import {
56
44
  USE_BEDROCK,
57
45
  USE_VERTEX,
58
46
  getModelManager,
59
47
  getVertexRegionForModel
60
- } from "./chunk-IZVMU4S2.js";
61
- import "./chunk-5PDP7R6N.js";
62
- import "./chunk-7U7L4NMD.js";
63
- import {
64
- getAnthropicApiKey,
65
- getGlobalConfig
66
- } from "./chunk-LC4TVOCZ.js";
67
- import "./chunk-UYXEDKOZ.js";
48
+ } from "./chunk-6ZWEOSEI.js";
68
49
  import {
69
50
  debug,
70
51
  getCurrentRequest,
@@ -72,166 +53,157 @@ import {
72
53
  logLLMInteraction,
73
54
  logSystemPromptConstruction,
74
55
  markPhase
75
- } from "./chunk-STSX7GIX.js";
56
+ } from "./chunk-YIO5EBMQ.js";
76
57
  import {
77
58
  PRODUCT_COMMAND,
78
59
  env,
79
- getCwd,
80
60
  logError
81
- } from "./chunk-YXYYDIMI.js";
61
+ } from "./chunk-3OEJVB5A.js";
62
+ import {
63
+ getCwd
64
+ } from "./chunk-BBJFHTBC.js";
65
+ import "./chunk-QHQOBUF6.js";
82
66
  import {
83
67
  MACRO
84
- } from "./chunk-F2SJXUDI.js";
68
+ } from "./chunk-W5EGGA44.js";
69
+ import "./chunk-DXD76CMV.js";
70
+ import "./chunk-LB6TCPDI.js";
85
71
  import {
86
- addToTotalCost
87
- } from "./chunk-EZXMVTDU.js";
88
- import "./chunk-JC6NCUG5.js";
72
+ getAnthropicApiKey,
73
+ getGlobalConfig
74
+ } from "./chunk-XR2W3MAM.js";
75
+ import "./chunk-B3MW3YGY.js";
76
+ import "./chunk-54KOYG5C.js";
89
77
 
90
- // src/services/ai/llm.ts
78
+ // packages/core/src/ai/llm.ts
91
79
  import "@anthropic-ai/sdk/shims/node";
92
- import Anthropic, { APIConnectionError, APIError } from "@anthropic-ai/sdk";
93
- import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
94
- import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";
95
- import chalk from "chalk";
96
- import { randomUUID } from "crypto";
80
+ import { randomUUID as randomUUID4 } from "crypto";
97
81
  import "dotenv/config";
98
82
 
99
- // src/utils/system/http.ts
100
- var USER_AGENT = `${PRODUCT_COMMAND}/${MACRO.VERSION} (${process.env.USER_TYPE})`;
83
+ // packages/core/src/ai/llm/openai/queryOpenAI.ts
84
+ import { randomUUID as randomUUID3 } from "crypto";
85
+ import { zodToJsonSchema as zodToJsonSchema4 } from "zod-to-json-schema";
101
86
 
102
- // src/services/system/vcr.ts
103
- import { createHash } from "crypto";
104
- import { mkdirSync, readFileSync, writeFileSync } from "fs";
105
- import { dirname } from "path";
106
- import { existsSync } from "fs";
107
- import * as path from "path";
108
- import { mapValues } from "lodash-es";
109
- async function withVCR(messages, f) {
110
- if (process.env.NODE_ENV !== "test") {
111
- return await f();
112
- }
113
- const dehydratedInput = mapMessages(
114
- messages.map((_) => _.message.content),
115
- dehydrateValue
116
- );
117
- const filename = `./fixtures/${dehydratedInput.map((_) => createHash("sha1").update(JSON.stringify(_)).digest("hex").slice(0, 6)).join("-")}.json`;
118
- if (existsSync(filename)) {
119
- const cached = JSON.parse(readFileSync(filename, "utf-8"));
120
- return mapAssistantMessage(cached.output, hydrateValue);
121
- }
122
- if (env.isCI) {
123
- process.stderr.write(
124
- `Anthropic API fixture missing. Re-run bun test locally, then commit the result. ${JSON.stringify({ input: dehydratedInput }, null, 2)}
125
- `
126
- );
127
- }
128
- const result = await f();
129
- if (env.isCI) {
130
- return result;
131
- }
132
- if (!existsSync(dirname(filename))) {
133
- mkdirSync(dirname(filename), { recursive: true });
134
- }
135
- writeFileSync(
136
- filename,
137
- JSON.stringify(
138
- {
139
- input: dehydratedInput,
140
- output: mapAssistantMessage(result, dehydrateValue)
141
- },
142
- null,
143
- 2
144
- )
145
- );
146
- return result;
87
+ // packages/core/src/ai/llm/systemPromptUtils.ts
88
+ var PROMPT_CACHING_ENABLED = !process.env.DISABLE_PROMPT_CACHING;
89
+ function splitSysPromptPrefix(systemPrompt) {
90
+ const systemPromptFirstBlock = systemPrompt[0] || "";
91
+ const systemPromptRest = systemPrompt.slice(1);
92
+ return [systemPromptFirstBlock, systemPromptRest.join("\n")].filter(Boolean);
147
93
  }
148
- function mapMessages(messages, f) {
149
- return messages.map((_) => {
150
- if (typeof _ === "string") {
151
- return f(_);
94
+
95
+ // packages/core/src/ai/llm/retry.ts
96
+ import "@anthropic-ai/sdk/shims/node";
97
+ import { APIConnectionError, APIError } from "@anthropic-ai/sdk";
98
+ var MAX_RETRIES = process.env.USER_TYPE === "SWE_BENCH" ? 100 : 10;
99
+ var BASE_DELAY_MS = 500;
100
+ function abortableDelay(delayMs, signal) {
101
+ return new Promise((resolve, reject) => {
102
+ if (signal?.aborted) {
103
+ reject(new Error("Request was aborted"));
104
+ return;
105
+ }
106
+ const timeoutId = setTimeout(() => {
107
+ resolve();
108
+ }, delayMs);
109
+ if (signal) {
110
+ const abortHandler = () => {
111
+ clearTimeout(timeoutId);
112
+ reject(new Error("Request was aborted"));
113
+ };
114
+ signal.addEventListener("abort", abortHandler, { once: true });
152
115
  }
153
- return _.map((_2) => {
154
- switch (_2.type) {
155
- case "tool_result":
156
- if (typeof _2.content === "string") {
157
- return { ..._2, content: f(_2.content) };
158
- }
159
- if (Array.isArray(_2.content)) {
160
- return {
161
- ..._2,
162
- content: _2.content.map((_3) => {
163
- switch (_3.type) {
164
- case "text":
165
- return { ..._3, text: f(_3.text) };
166
- case "image":
167
- return _3;
168
- }
169
- })
170
- };
171
- }
172
- return _2;
173
- case "text":
174
- return { ..._2, text: f(_2.text) };
175
- case "tool_use":
176
- return {
177
- ..._2,
178
- input: mapValues(_2.input, f)
179
- };
180
- case "image":
181
- return _2;
182
- }
183
- });
184
116
  });
185
117
  }
186
- function mapAssistantMessage(message, f) {
187
- return {
188
- durationMs: "DURATION",
189
- costUSD: "COST",
190
- uuid: "UUID",
191
- message: {
192
- ...message.message,
193
- content: message.message.content.map((_) => {
194
- switch (_.type) {
195
- case "text":
196
- return {
197
- ..._,
198
- text: f(_.text),
199
- citations: _.citations || []
200
- };
201
- case "tool_use":
202
- return {
203
- ..._,
204
- input: mapValues(_.input, f)
205
- };
206
- default:
207
- return _;
208
- }
209
- }).filter(Boolean)
210
- },
211
- type: "assistant"
212
- };
118
+ function getRetryDelay(attempt, retryAfterHeader) {
119
+ if (retryAfterHeader) {
120
+ const seconds = parseInt(retryAfterHeader, 10);
121
+ if (!isNaN(seconds)) {
122
+ return seconds * 1e3;
123
+ }
124
+ }
125
+ return Math.min(BASE_DELAY_MS * Math.pow(2, attempt - 1), 32e3);
213
126
  }
214
- function dehydrateValue(s) {
215
- if (typeof s !== "string") {
216
- return s;
127
+ function shouldRetry(error) {
128
+ if (error.message?.includes('"type":"overloaded_error"')) {
129
+ return process.env.USER_TYPE === "SWE_BENCH";
217
130
  }
218
- const s1 = s.replace(/num_files="\d+"/g, 'num_files="[NUM]"').replace(/duration_ms="\d+"/g, 'duration_ms="[DURATION]"').replace(/cost_usd="\d+"/g, 'cost_usd="[COST]"').replace(/\//g, path.sep).replaceAll(getCwd(), "[CWD]");
219
- if (s1.includes("Files modified by user:")) {
220
- return "Files modified by user: [FILES]";
131
+ const shouldRetryHeader = error.headers?.["x-should-retry"];
132
+ if (shouldRetryHeader === "true") return true;
133
+ if (shouldRetryHeader === "false") return false;
134
+ if (error instanceof APIConnectionError) {
135
+ return true;
221
136
  }
222
- return s1;
137
+ if (!error.status) return false;
138
+ if (error.status === 408) return true;
139
+ if (error.status === 409) return true;
140
+ if (error.status === 429) return true;
141
+ if (error.status && error.status >= 500) return true;
142
+ return false;
223
143
  }
224
- function hydrateValue(s) {
225
- if (typeof s !== "string") {
226
- return s;
144
+ async function withRetry(operation, options = {}) {
145
+ const maxRetries = options.maxRetries ?? MAX_RETRIES;
146
+ let lastError;
147
+ for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
148
+ try {
149
+ return await operation(attempt);
150
+ } catch (error) {
151
+ lastError = error;
152
+ if (attempt > maxRetries || !(error instanceof APIError) || !shouldRetry(error)) {
153
+ throw error;
154
+ }
155
+ if (options.signal?.aborted) {
156
+ throw new Error("Request cancelled by user");
157
+ }
158
+ const retryAfter = error.headers?.["retry-after"] ?? null;
159
+ const delayMs = getRetryDelay(attempt, retryAfter);
160
+ debug.warn("LLM_API_RETRY", {
161
+ name: error.name,
162
+ message: error.message,
163
+ status: error.status,
164
+ attempt,
165
+ maxRetries,
166
+ delayMs
167
+ });
168
+ try {
169
+ await abortableDelay(delayMs, options.signal);
170
+ } catch (delayError) {
171
+ if (delayError.message === "Request was aborted") {
172
+ throw new Error("Request cancelled by user");
173
+ }
174
+ throw delayError;
175
+ }
176
+ }
227
177
  }
228
- return s.replaceAll("[NUM]", "1").replaceAll("[DURATION]", "100").replaceAll("[CWD]", getCwd());
178
+ throw lastError;
229
179
  }
230
180
 
231
- // src/services/ai/llm.ts
232
- import { zodToJsonSchema as zodToJsonSchema4 } from "zod-to-json-schema";
181
+ // packages/core/src/ai/llm/errors.ts
182
+ function getAssistantMessageFromError(error) {
183
+ if (error instanceof Error && error.message.includes("prompt is too long")) {
184
+ return createAssistantAPIErrorMessage(PROMPT_TOO_LONG_ERROR_MESSAGE);
185
+ }
186
+ if (error instanceof Error && error.message.includes("Your credit balance is too low")) {
187
+ return createAssistantAPIErrorMessage(CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE);
188
+ }
189
+ if (error instanceof Error && error.message.toLowerCase().includes("x-api-key")) {
190
+ return createAssistantAPIErrorMessage(INVALID_API_KEY_ERROR_MESSAGE);
191
+ }
192
+ if (error instanceof Error) {
193
+ if (process.env.NODE_ENV === "development") {
194
+ debug.error("ANTHROPIC_API_ERROR", {
195
+ message: error.message,
196
+ stack: error.stack
197
+ });
198
+ }
199
+ return createAssistantAPIErrorMessage(
200
+ `${API_ERROR_MESSAGE_PREFIX}: ${error.message}`
201
+ );
202
+ }
203
+ return createAssistantAPIErrorMessage(API_ERROR_MESSAGE_PREFIX);
204
+ }
233
205
 
234
- // src/services/ai/adapters/base.ts
206
+ // packages/core/src/ai/adapters/base.ts
235
207
  function normalizeTokens(apiResponse) {
236
208
  if (!apiResponse || typeof apiResponse !== "object") {
237
209
  return { input: 0, output: 0 };
@@ -257,13 +229,16 @@ var ModelAPIAdapter = class {
257
229
  this.modelProfile = modelProfile;
258
230
  }
259
231
  cumulativeUsage = { input: 0, output: 0 };
232
+ // Optional: subclasses can implement streaming for real-time updates
233
+ // Default implementation yields no events (not supported)
260
234
  async *parseStreamingResponse(response, signal) {
261
235
  return;
262
- yield;
263
236
  }
237
+ // Reset cumulative usage for new requests
264
238
  resetCumulativeUsage() {
265
239
  this.cumulativeUsage = { input: 0, output: 0 };
266
240
  }
241
+ // Safely update cumulative usage
267
242
  updateCumulativeUsage(usage) {
268
243
  this.cumulativeUsage.input += usage.input;
269
244
  this.cumulativeUsage.output += usage.output;
@@ -274,6 +249,7 @@ var ModelAPIAdapter = class {
274
249
  this.cumulativeUsage.reasoning = (this.cumulativeUsage.reasoning || 0) + usage.reasoning;
275
250
  }
276
251
  }
252
+ // Shared utility methods
277
253
  getMaxTokensParam() {
278
254
  return this.capabilities.parameters.maxTokensField;
279
255
  }
@@ -294,12 +270,26 @@ var ModelAPIAdapter = class {
294
270
  }
295
271
  };
296
272
 
297
- // src/services/ai/adapters/openaiAdapter.ts
273
+ // packages/core/src/tooling/Tool.ts
274
+ function getToolDescription(tool) {
275
+ if (tool.cachedDescription) {
276
+ return tool.cachedDescription;
277
+ }
278
+ if (typeof tool.description === "string") {
279
+ return tool.description;
280
+ }
281
+ return `Tool: ${tool.name}`;
282
+ }
283
+
284
+ // packages/core/src/ai/adapters/openaiAdapter.ts
298
285
  import { zodToJsonSchema } from "zod-to-json-schema";
299
286
  var OpenAIAdapter = class extends ModelAPIAdapter {
300
287
  constructor(capabilities, modelProfile) {
301
288
  super(capabilities, modelProfile);
302
289
  }
290
+ /**
291
+ * Unified parseResponse that handles both streaming and non-streaming responses
292
+ */
303
293
  async parseResponse(response) {
304
294
  if (response?.body instanceof ReadableStream) {
305
295
  const { assistantMessage } = await this.parseStreamingOpenAIResponse(response);
@@ -320,6 +310,9 @@ var OpenAIAdapter = class extends ModelAPIAdapter {
320
310
  }
321
311
  return this.parseNonStreamingResponse(response);
322
312
  }
313
+ /**
314
+ * Common streaming response parser for all OpenAI APIs
315
+ */
323
316
  async *parseStreamingResponse(response) {
324
317
  const reader = response.body.getReader();
325
318
  const decoder = new TextDecoder();
@@ -387,6 +380,9 @@ var OpenAIAdapter = class extends ModelAPIAdapter {
387
380
  }
388
381
  };
389
382
  }
383
+ /**
384
+ * Parse SSE chunk - common for all OpenAI APIs
385
+ */
390
386
  parseSSEChunk(line) {
391
387
  if (line.startsWith("data: ")) {
392
388
  const data = line.slice(6).trim();
@@ -407,6 +403,9 @@ var OpenAIAdapter = class extends ModelAPIAdapter {
407
403
  }
408
404
  return null;
409
405
  }
406
+ /**
407
+ * Common helper for processing text deltas
408
+ */
410
409
  handleTextDelta(delta, responseId, hasStarted) {
411
410
  const events = [];
412
411
  if (!hasStarted && delta) {
@@ -428,6 +427,9 @@ var OpenAIAdapter = class extends ModelAPIAdapter {
428
427
  }
429
428
  return events;
430
429
  }
430
+ /**
431
+ * Common usage normalization
432
+ */
431
433
  normalizeUsageForAdapter(usage) {
432
434
  if (!usage) {
433
435
  return {
@@ -451,6 +453,9 @@ var OpenAIAdapter = class extends ModelAPIAdapter {
451
453
  reasoningTokens: usage.reasoningTokens ?? 0
452
454
  };
453
455
  }
456
+ /**
457
+ * Common tool building logic
458
+ */
454
459
  buildTools(tools) {
455
460
  return tools.map((tool) => ({
456
461
  type: "function",
@@ -463,22 +468,202 @@ var OpenAIAdapter = class extends ModelAPIAdapter {
463
468
  }
464
469
  };
465
470
 
466
- // src/services/ai/adapters/responsesAPI.ts
471
+ // packages/core/src/ai/adapters/responsesAPI.ts
467
472
  import { zodToJsonSchema as zodToJsonSchema2 } from "zod-to-json-schema";
468
- var ResponsesAPIAdapter = class extends OpenAIAdapter {
469
- createRequest(params) {
470
- const {
471
- messages,
472
- systemPrompt,
473
- tools,
474
- maxTokens,
475
- reasoningEffort,
476
- stopSequences
473
+
474
+ // packages/core/src/ai/adapters/responsesAPI/messageInput.ts
475
+ function convertMessagesToInput(messages) {
476
+ const inputItems = [];
477
+ for (const message of messages) {
478
+ const role = message.role;
479
+ if (role === "tool") {
480
+ const callId = message.tool_call_id || message.id;
481
+ if (typeof callId === "string" && callId) {
482
+ let content2 = message.content || "";
483
+ if (Array.isArray(content2)) {
484
+ const texts = [];
485
+ for (const part of content2) {
486
+ if (typeof part === "object" && part !== null) {
487
+ const t = part.text || part.content;
488
+ if (typeof t === "string" && t) {
489
+ texts.push(t);
490
+ }
491
+ }
492
+ }
493
+ content2 = texts.join("\n");
494
+ }
495
+ if (typeof content2 === "string") {
496
+ inputItems.push({
497
+ type: "function_call_output",
498
+ call_id: callId,
499
+ output: content2
500
+ });
501
+ }
502
+ }
503
+ continue;
504
+ }
505
+ if (role === "assistant" && Array.isArray(message.tool_calls)) {
506
+ for (const tc of message.tool_calls) {
507
+ if (typeof tc !== "object" || tc === null) {
508
+ continue;
509
+ }
510
+ const tcType = tc.type || "function";
511
+ if (tcType !== "function") {
512
+ continue;
513
+ }
514
+ const callId = tc.id || tc.call_id;
515
+ const fn = tc.function;
516
+ const name = typeof fn === "object" && fn !== null ? fn.name : null;
517
+ const args = typeof fn === "object" && fn !== null ? fn.arguments : null;
518
+ if (typeof callId === "string" && typeof name === "string" && typeof args === "string") {
519
+ inputItems.push({
520
+ type: "function_call",
521
+ name,
522
+ arguments: args,
523
+ call_id: callId
524
+ });
525
+ }
526
+ }
527
+ continue;
528
+ }
529
+ const content = message.content || "";
530
+ const contentItems = [];
531
+ if (Array.isArray(content)) {
532
+ for (const part of content) {
533
+ if (typeof part !== "object" || part === null) continue;
534
+ const ptype = part.type;
535
+ if (ptype === "text") {
536
+ const text = part.text || part.content || "";
537
+ if (typeof text === "string" && text) {
538
+ const kind = role === "assistant" ? "output_text" : "input_text";
539
+ contentItems.push({ type: kind, text });
540
+ }
541
+ } else if (ptype === "image_url") {
542
+ const image = part.image_url;
543
+ const url = typeof image === "object" && image !== null ? image.url : image;
544
+ if (typeof url === "string" && url) {
545
+ contentItems.push({ type: "input_image", image_url: url });
546
+ }
547
+ }
548
+ }
549
+ } else if (typeof content === "string" && content) {
550
+ const kind = role === "assistant" ? "output_text" : "input_text";
551
+ contentItems.push({ type: kind, text: content });
552
+ }
553
+ if (contentItems.length) {
554
+ const roleOut = role === "assistant" ? "assistant" : "user";
555
+ inputItems.push({
556
+ type: "message",
557
+ role: roleOut,
558
+ content: contentItems
559
+ });
560
+ }
561
+ }
562
+ return inputItems;
563
+ }
564
+ function buildInstructions(systemPrompt) {
565
+ const systemContent = systemPrompt.filter((content) => content.trim()).join("\n\n");
566
+ return systemContent;
567
+ }
568
+
569
+ // packages/core/src/ai/adapters/responsesAPI/nonStreaming.ts
570
+ function parseToolCalls(response) {
571
+ if (!response.output || !Array.isArray(response.output)) {
572
+ return [];
573
+ }
574
+ const toolCalls = [];
575
+ for (const item of response.output) {
576
+ if (item.type === "function_call") {
577
+ const callId = item.call_id || item.id;
578
+ const name = item.name || "";
579
+ const args = item.arguments || "{}";
580
+ if (typeof callId === "string" && typeof name === "string" && typeof args === "string") {
581
+ toolCalls.push({
582
+ id: callId,
583
+ type: "function",
584
+ function: {
585
+ name,
586
+ arguments: args
587
+ }
588
+ });
589
+ }
590
+ } else if (item.type === "tool_call") {
591
+ const callId = item.id || `tool_${Math.random().toString(36).substring(2, 15)}`;
592
+ toolCalls.push({
593
+ id: callId,
594
+ type: "tool_call",
595
+ name: item.name,
596
+ arguments: item.arguments
597
+ });
598
+ }
599
+ }
600
+ return toolCalls;
601
+ }
602
+ function parseNonStreamingResponse(response) {
603
+ let content = response.output_text || "";
604
+ let reasoningContent = "";
605
+ if (response.output && Array.isArray(response.output)) {
606
+ const messageItems = response.output.filter(
607
+ (item) => item.type === "message"
608
+ );
609
+ if (messageItems.length > 0) {
610
+ content = messageItems.map((item) => {
611
+ if (item.content && Array.isArray(item.content)) {
612
+ return item.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
613
+ }
614
+ return item.content || "";
615
+ }).filter(Boolean).join("\n\n");
616
+ }
617
+ const reasoningItems = response.output.filter(
618
+ (item) => item.type === "reasoning"
619
+ );
620
+ if (reasoningItems.length > 0) {
621
+ reasoningContent = reasoningItems.map((item) => item.content || "").filter(Boolean).join("\n\n");
622
+ }
623
+ }
624
+ if (reasoningContent) {
625
+ const thinkBlock = `
626
+
627
+ ${reasoningContent}
628
+
629
+ `;
630
+ content = thinkBlock + content;
631
+ }
632
+ const toolCalls = parseToolCalls(response);
633
+ const contentArray = content ? [{ type: "text", text: content, citations: [] }] : [{ type: "text", text: "", citations: [] }];
634
+ const promptTokens = response.usage?.input_tokens || 0;
635
+ const completionTokens = response.usage?.output_tokens || 0;
636
+ const totalTokens = response.usage?.total_tokens ?? promptTokens + completionTokens;
637
+ return {
638
+ id: response.id || `resp_${Date.now()}`,
639
+ content: contentArray,
640
+ // Return as array (Anthropic format)
641
+ toolCalls,
642
+ usage: {
643
+ promptTokens,
644
+ completionTokens,
645
+ reasoningTokens: response.usage?.output_tokens_details?.reasoning_tokens
646
+ },
647
+ responseId: response.id
648
+ // Save for state management
649
+ };
650
+ }
651
+
652
+ // packages/core/src/ai/adapters/responsesAPI.ts
653
+ var ResponsesAPIAdapter = class extends OpenAIAdapter {
654
+ createRequest(params) {
655
+ const {
656
+ messages,
657
+ systemPrompt,
658
+ tools,
659
+ maxTokens,
660
+ reasoningEffort,
661
+ stopSequences
477
662
  } = params;
478
663
  const request = {
479
664
  model: this.modelProfile.modelName,
480
- input: this.convertMessagesToInput(messages),
481
- instructions: this.buildInstructions(systemPrompt)
665
+ input: convertMessagesToInput(messages),
666
+ instructions: buildInstructions(systemPrompt)
482
667
  };
483
668
  const maxTokensField = this.getMaxTokensParam();
484
669
  request[maxTokensField] = maxTokens;
@@ -530,17 +715,19 @@ var ResponsesAPIAdapter = class extends OpenAIAdapter {
530
715
  return request;
531
716
  }
532
717
  buildTools(tools) {
718
+ const isPlainObject = (obj) => {
719
+ return obj !== null && typeof obj === "object" && !Array.isArray(obj);
720
+ };
533
721
  return tools.map((tool) => {
534
722
  let parameters = tool.inputJSONSchema;
535
723
  if (!parameters && tool.inputSchema) {
536
- const isPlainObject = (obj) => {
537
- return obj !== null && typeof obj === "object" && !Array.isArray(obj);
538
- };
539
- if (isPlainObject(tool.inputSchema) && ("type" in tool.inputSchema || "properties" in tool.inputSchema)) {
540
- parameters = tool.inputSchema;
724
+ const inputSchema = tool.inputSchema;
725
+ if (isPlainObject(inputSchema) && ("type" in inputSchema || "properties" in inputSchema)) {
726
+ parameters = inputSchema;
541
727
  } else {
542
728
  try {
543
- parameters = zodToJsonSchema2(tool.inputSchema);
729
+ const converted = zodToJsonSchema2(tool.inputSchema);
730
+ parameters = isPlainObject(converted) && ("type" in converted || "properties" in converted) ? converted : { type: "object", properties: {} };
544
731
  } catch (error) {
545
732
  logError(error);
546
733
  debug.warn("RESPONSES_API_TOOL_SCHEMA_CONVERSION_FAILED", {
@@ -555,10 +742,11 @@ var ResponsesAPIAdapter = class extends OpenAIAdapter {
555
742
  type: "function",
556
743
  name: tool.name,
557
744
  description: getToolDescription(tool),
558
- parameters: parameters || { type: "object", properties: {} }
745
+ parameters: parameters ?? { type: "object", properties: {} }
559
746
  };
560
747
  });
561
748
  }
749
+ // Override parseResponse to handle Response API directly without double conversion
562
750
  async parseResponse(response) {
563
751
  if (response?.body instanceof ReadableStream) {
564
752
  const { assistantMessage } = await processResponsesStream(
@@ -579,53 +767,11 @@ var ResponsesAPIAdapter = class extends OpenAIAdapter {
579
767
  }
580
768
  return this.parseNonStreamingResponse(response);
581
769
  }
770
+ // Implement abstract method from OpenAIAdapter
582
771
  parseNonStreamingResponse(response) {
583
- let content = response.output_text || "";
584
- let reasoningContent = "";
585
- if (response.output && Array.isArray(response.output)) {
586
- const messageItems = response.output.filter(
587
- (item) => item.type === "message"
588
- );
589
- if (messageItems.length > 0) {
590
- content = messageItems.map((item) => {
591
- if (item.content && Array.isArray(item.content)) {
592
- return item.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
593
- }
594
- return item.content || "";
595
- }).filter(Boolean).join("\n\n");
596
- }
597
- const reasoningItems = response.output.filter(
598
- (item) => item.type === "reasoning"
599
- );
600
- if (reasoningItems.length > 0) {
601
- reasoningContent = reasoningItems.map((item) => item.content || "").filter(Boolean).join("\n\n");
602
- }
603
- }
604
- if (reasoningContent) {
605
- const thinkBlock = `
606
-
607
- ${reasoningContent}
608
-
609
- `;
610
- content = thinkBlock + content;
611
- }
612
- const toolCalls = this.parseToolCalls(response);
613
- const contentArray = content ? [{ type: "text", text: content, citations: [] }] : [{ type: "text", text: "", citations: [] }];
614
- const promptTokens = response.usage?.input_tokens || 0;
615
- const completionTokens = response.usage?.output_tokens || 0;
616
- const totalTokens = response.usage?.total_tokens ?? promptTokens + completionTokens;
617
- return {
618
- id: response.id || `resp_${Date.now()}`,
619
- content: contentArray,
620
- toolCalls,
621
- usage: {
622
- promptTokens,
623
- completionTokens,
624
- reasoningTokens: response.usage?.output_tokens_details?.reasoning_tokens
625
- },
626
- responseId: response.id
627
- };
772
+ return parseNonStreamingResponse(response);
628
773
  }
774
+ // Implement abstract method from OpenAIAdapter - Responses API specific streaming logic
629
775
  async *processStreamingChunk(parsed, responseId, hasStarted, accumulatedContent, reasoningContext) {
630
776
  if (parsed.type === "response.reasoning_summary_part.added") {
631
777
  const partIndex = parsed.summary_index || 0;
@@ -714,14 +860,17 @@ ${reasoningContent}
714
860
  }
715
861
  return state;
716
862
  }
863
+ // parseStreamingResponse and parseSSEChunk are now handled by the base OpenAIAdapter class
864
+ // Implement abstract method for parsing streaming OpenAI responses
717
865
  async parseStreamingOpenAIResponse(response) {
718
- const { processResponsesStream: processResponsesStream2 } = await import("./responsesStreaming-AW344PQO.js");
866
+ const { processResponsesStream: processResponsesStream2 } = await import("./responsesStreaming-JNGE2P3D.js");
719
867
  return await processResponsesStream2(
720
868
  this.parseStreamingResponse(response),
721
869
  Date.now(),
722
870
  response.id ?? `resp_${Date.now()}`
723
871
  );
724
872
  }
873
+ // Implement abstract method for usage normalization
725
874
  normalizeUsageForAdapter(usage) {
726
875
  const baseUsage = super.normalizeUsageForAdapter(usage);
727
876
  return {
@@ -729,153 +878,10 @@ ${reasoningContent}
729
878
  reasoningTokens: usage?.output_tokens_details?.reasoning_tokens ?? 0
730
879
  };
731
880
  }
732
- convertMessagesToInput(messages) {
733
- const inputItems = [];
734
- for (const message of messages) {
735
- const role = message.role;
736
- if (role === "tool") {
737
- const callId = message.tool_call_id || message.id;
738
- if (typeof callId === "string" && callId) {
739
- let content2 = message.content || "";
740
- if (Array.isArray(content2)) {
741
- const texts = [];
742
- for (const part of content2) {
743
- if (typeof part === "object" && part !== null) {
744
- const t = part.text || part.content;
745
- if (typeof t === "string" && t) {
746
- texts.push(t);
747
- }
748
- }
749
- }
750
- content2 = texts.join("\n");
751
- }
752
- if (typeof content2 === "string") {
753
- inputItems.push({
754
- type: "function_call_output",
755
- call_id: callId,
756
- output: content2
757
- });
758
- }
759
- }
760
- continue;
761
- }
762
- if (role === "assistant" && Array.isArray(message.tool_calls)) {
763
- for (const tc of message.tool_calls) {
764
- if (typeof tc !== "object" || tc === null) {
765
- continue;
766
- }
767
- const tcType = tc.type || "function";
768
- if (tcType !== "function") {
769
- continue;
770
- }
771
- const callId = tc.id || tc.call_id;
772
- const fn = tc.function;
773
- const name = typeof fn === "object" && fn !== null ? fn.name : null;
774
- const args = typeof fn === "object" && fn !== null ? fn.arguments : null;
775
- if (typeof callId === "string" && typeof name === "string" && typeof args === "string") {
776
- inputItems.push({
777
- type: "function_call",
778
- name,
779
- arguments: args,
780
- call_id: callId
781
- });
782
- }
783
- }
784
- continue;
785
- }
786
- const content = message.content || "";
787
- const contentItems = [];
788
- if (Array.isArray(content)) {
789
- for (const part of content) {
790
- if (typeof part !== "object" || part === null) continue;
791
- const ptype = part.type;
792
- if (ptype === "text") {
793
- const text = part.text || part.content || "";
794
- if (typeof text === "string" && text) {
795
- const kind = role === "assistant" ? "output_text" : "input_text";
796
- contentItems.push({ type: kind, text });
797
- }
798
- } else if (ptype === "image_url") {
799
- const image = part.image_url;
800
- const url = typeof image === "object" && image !== null ? image.url : image;
801
- if (typeof url === "string" && url) {
802
- contentItems.push({ type: "input_image", image_url: url });
803
- }
804
- }
805
- }
806
- } else if (typeof content === "string" && content) {
807
- const kind = role === "assistant" ? "output_text" : "input_text";
808
- contentItems.push({ type: kind, text: content });
809
- }
810
- if (contentItems.length) {
811
- const roleOut = role === "assistant" ? "assistant" : "user";
812
- inputItems.push({
813
- type: "message",
814
- role: roleOut,
815
- content: contentItems
816
- });
817
- }
818
- }
819
- return inputItems;
820
- }
821
- buildInstructions(systemPrompt) {
822
- const systemContent = systemPrompt.filter((content) => content.trim()).join("\n\n");
823
- return systemContent;
824
- }
825
- parseToolCalls(response) {
826
- if (!response.output || !Array.isArray(response.output)) {
827
- return [];
828
- }
829
- const toolCalls = [];
830
- for (const item of response.output) {
831
- if (item.type === "function_call") {
832
- const callId = item.call_id || item.id;
833
- const name = item.name || "";
834
- const args = item.arguments || "{}";
835
- if (typeof callId === "string" && typeof name === "string" && typeof args === "string") {
836
- toolCalls.push({
837
- id: callId,
838
- type: "function",
839
- function: {
840
- name,
841
- arguments: args
842
- }
843
- });
844
- }
845
- } else if (item.type === "tool_call") {
846
- const callId = item.id || `tool_${Math.random().toString(36).substring(2, 15)}`;
847
- toolCalls.push({
848
- id: callId,
849
- type: "tool_call",
850
- name: item.name,
851
- arguments: item.arguments
852
- });
853
- }
854
- }
855
- return toolCalls;
856
- }
857
- applyReasoningToMessage(message, reasoningSummaryText, reasoningFullText) {
858
- const rtxtParts = [];
859
- if (typeof reasoningSummaryText === "string" && reasoningSummaryText.trim()) {
860
- rtxtParts.push(reasoningSummaryText);
861
- }
862
- if (typeof reasoningFullText === "string" && reasoningFullText.trim()) {
863
- rtxtParts.push(reasoningFullText);
864
- }
865
- const rtxt = rtxtParts.filter((p) => p).join("\n\n");
866
- if (rtxt) {
867
- const thinkBlock = `<think>
868
- ${rtxt}
869
- </think>
870
- `;
871
- const contentText = message.content || "";
872
- message.content = thinkBlock + (typeof contentText === "string" ? contentText : "");
873
- }
874
- return message;
875
- }
876
881
  };
877
882
 
878
- // src/services/ai/adapters/chatCompletions.ts
883
+ // packages/core/src/ai/adapters/chatCompletions.ts
884
+ import { randomUUID } from "crypto";
879
885
  import { zodToJsonSchema as zodToJsonSchema3 } from "zod-to-json-schema";
880
886
  var ChatCompletionsAdapter = class extends OpenAIAdapter {
881
887
  createRequest(params) {
@@ -924,6 +930,8 @@ var ChatCompletionsAdapter = class extends OpenAIAdapter {
924
930
  }
925
931
  }));
926
932
  }
933
+ // parseResponse is now handled by the base OpenAIAdapter class
934
+ // Implement abstract method from OpenAIAdapter - Chat Completions specific non-streaming
927
935
  parseNonStreamingResponse(response) {
928
936
  if (!response || typeof response !== "object") {
929
937
  throw new Error("Invalid response: response must be an object");
@@ -980,6 +988,7 @@ var ChatCompletionsAdapter = class extends OpenAIAdapter {
980
988
  return msg;
981
989
  });
982
990
  }
991
+ // Implement abstract method from OpenAIAdapter - Chat Completions specific streaming logic
983
992
  async *processStreamingChunk(parsed, responseId, hasStarted, accumulatedContent, reasoningContext) {
984
993
  if (!parsed || typeof parsed !== "object") {
985
994
  return;
@@ -1037,6 +1046,7 @@ var ChatCompletionsAdapter = class extends OpenAIAdapter {
1037
1046
  }
1038
1047
  return state;
1039
1048
  }
1049
+ // Implement abstract method for parsing streaming OpenAI responses
1040
1050
  async parseStreamingOpenAIResponse(response, signal) {
1041
1051
  const contentBlocks = [];
1042
1052
  const usage = {
@@ -1104,7 +1114,7 @@ var ChatCompletionsAdapter = class extends OpenAIAdapter {
1104
1114
  },
1105
1115
  costUSD: 0,
1106
1116
  durationMs: Date.now() - Date.now(),
1107
- uuid: `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
1117
+ uuid: randomUUID(),
1108
1118
  responseId
1109
1119
  };
1110
1120
  return {
@@ -1147,7 +1157,8 @@ var ChatCompletionsAdapter = class extends OpenAIAdapter {
1147
1157
  },
1148
1158
  costUSD: 0,
1149
1159
  durationMs: Date.now() - Date.now(),
1150
- uuid: `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
1160
+ // Placeholder
1161
+ uuid: randomUUID(),
1151
1162
  responseId
1152
1163
  };
1153
1164
  return {
@@ -1164,7 +1175,7 @@ var ChatCompletionsAdapter = class extends OpenAIAdapter {
1164
1175
  }
1165
1176
  };
1166
1177
 
1167
- // src/constants/modelCapabilities.ts
1178
+ // packages/core/src/constants/modelCapabilities.ts
1168
1179
  var GPT5_CAPABILITIES = {
1169
1180
  apiArchitecture: {
1170
1181
  primary: "responses_api",
@@ -1172,6 +1183,7 @@ var GPT5_CAPABILITIES = {
1172
1183
  },
1173
1184
  parameters: {
1174
1185
  maxTokensField: "max_output_tokens",
1186
+ // Responses API uses max_output_tokens
1175
1187
  supportsReasoningEffort: true,
1176
1188
  supportsVerbosity: true,
1177
1189
  temperatureMode: "fixed_one"
@@ -1189,6 +1201,7 @@ var GPT5_CAPABILITIES = {
1189
1201
  },
1190
1202
  streaming: {
1191
1203
  supported: true,
1204
+ // Responses API supports streaming
1192
1205
  includesUsage: true
1193
1206
  }
1194
1207
  };
@@ -1219,18 +1232,22 @@ var CHAT_COMPLETIONS_CAPABILITIES = {
1219
1232
  }
1220
1233
  };
1221
1234
  var MODEL_CAPABILITIES_REGISTRY = {
1235
+ // GPT-5 series
1222
1236
  "gpt-5": GPT5_CAPABILITIES,
1223
1237
  "gpt-5-mini": GPT5_CAPABILITIES,
1224
1238
  "gpt-5-nano": GPT5_CAPABILITIES,
1225
1239
  "gpt-5-chat-latest": GPT5_CAPABILITIES,
1226
1240
  "gpt-5-codex": GPT5_CAPABILITIES,
1241
+ // GPT-4 series
1227
1242
  "gpt-4o": CHAT_COMPLETIONS_CAPABILITIES,
1228
1243
  "gpt-4o-mini": CHAT_COMPLETIONS_CAPABILITIES,
1229
1244
  "gpt-4-turbo": CHAT_COMPLETIONS_CAPABILITIES,
1230
1245
  "gpt-4": CHAT_COMPLETIONS_CAPABILITIES,
1246
+ // Claude series (supported through conversion layer)
1231
1247
  "claude-3-5-sonnet-20241022": CHAT_COMPLETIONS_CAPABILITIES,
1232
1248
  "claude-3-5-haiku-20241022": CHAT_COMPLETIONS_CAPABILITIES,
1233
1249
  "claude-3-opus-20240229": CHAT_COMPLETIONS_CAPABILITIES,
1250
+ // O1 series (special reasoning models)
1234
1251
  o1: {
1235
1252
  ...CHAT_COMPLETIONS_CAPABILITIES,
1236
1253
  parameters: {
@@ -1274,6 +1291,7 @@ function inferModelCapabilities(modelName) {
1274
1291
  toolCalling: {
1275
1292
  ...CHAT_COMPLETIONS_CAPABILITIES.toolCalling,
1276
1293
  supportsAllowedTools: false
1294
+ // GLM might not support this
1277
1295
  }
1278
1296
  };
1279
1297
  }
@@ -1309,8 +1327,11 @@ function getModelCapabilities(modelName) {
1309
1327
  return defaultCapabilities;
1310
1328
  }
1311
1329
 
1312
- // src/services/ai/modelAdapterFactory.ts
1330
+ // packages/core/src/ai/modelAdapterFactory.ts
1313
1331
  var ModelAdapterFactory = class {
1332
+ /**
1333
+ * Create appropriate adapter based on model configuration
1334
+ */
1314
1335
  static createAdapter(modelProfile) {
1315
1336
  const capabilities = getModelCapabilities(modelProfile.modelName);
1316
1337
  const apiType = this.determineAPIType(modelProfile, capabilities);
@@ -1322,6 +1343,9 @@ var ModelAdapterFactory = class {
1322
1343
  return new ChatCompletionsAdapter(capabilities, modelProfile);
1323
1344
  }
1324
1345
  }
1346
+ /**
1347
+ * Determine which API should be used
1348
+ */
1325
1349
  static determineAPIType(modelProfile, capabilities) {
1326
1350
  if (capabilities.apiArchitecture.primary !== "responses_api") {
1327
1351
  return "chat_completions";
@@ -1335,6 +1359,9 @@ var ModelAdapterFactory = class {
1335
1359
  }
1336
1360
  return capabilities.apiArchitecture.primary;
1337
1361
  }
1362
+ /**
1363
+ * Check if model should use Responses API
1364
+ */
1338
1365
  static shouldUseResponsesAPI(modelProfile) {
1339
1366
  const capabilities = getModelCapabilities(modelProfile.modelName);
1340
1367
  const apiType = this.determineAPIType(modelProfile, capabilities);
@@ -1342,254 +1369,39 @@ var ModelAdapterFactory = class {
1342
1369
  }
1343
1370
  };
1344
1371
 
1345
- // src/services/ai/responseStateManager.ts
1346
- var ResponseStateManager = class {
1347
- conversationStates = /* @__PURE__ */ new Map();
1348
- CLEANUP_INTERVAL = 60 * 60 * 1e3;
1349
- constructor() {
1350
- setInterval(() => {
1351
- this.cleanup();
1352
- }, this.CLEANUP_INTERVAL);
1353
- }
1354
- setPreviousResponseId(conversationId, responseId) {
1355
- this.conversationStates.set(conversationId, {
1356
- previousResponseId: responseId,
1357
- lastUpdate: Date.now()
1358
- });
1359
- }
1360
- getPreviousResponseId(conversationId) {
1361
- const state = this.conversationStates.get(conversationId);
1362
- if (state) {
1363
- state.lastUpdate = Date.now();
1364
- return state.previousResponseId;
1365
- }
1366
- return void 0;
1367
- }
1368
- clearConversation(conversationId) {
1369
- this.conversationStates.delete(conversationId);
1370
- }
1371
- clearAll() {
1372
- this.conversationStates.clear();
1373
- }
1374
- cleanup() {
1375
- const now = Date.now();
1376
- for (const [conversationId, state] of this.conversationStates.entries()) {
1377
- if (now - state.lastUpdate > this.CLEANUP_INTERVAL) {
1378
- this.conversationStates.delete(conversationId);
1379
- }
1380
- }
1381
- }
1382
- getStateSize() {
1383
- return this.conversationStates.size;
1384
- }
1385
- };
1386
- var responseStateManager = new ResponseStateManager();
1387
- function getConversationId(agentId, messageId) {
1388
- return agentId || messageId || `conv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1389
- }
1390
-
1391
- // src/services/ai/llm.ts
1372
+ // packages/core/src/ai/llm/openai/conversion.ts
1392
1373
  import { nanoid } from "nanoid";
1393
1374
 
1394
- // src/utils/tooling/toolUsePartialJson.ts
1395
- function tokenizePartialJson(input) {
1396
- let index = 0;
1397
- const tokens = [];
1398
- while (index < input.length) {
1399
- let ch = input[index];
1400
- if (ch === "\\") {
1401
- index++;
1402
- continue;
1403
- }
1404
- if (ch === "{") {
1405
- tokens.push({ type: "brace", value: "{" });
1406
- index++;
1407
- continue;
1408
- }
1409
- if (ch === "}") {
1410
- tokens.push({ type: "brace", value: "}" });
1411
- index++;
1412
- continue;
1413
- }
1414
- if (ch === "[") {
1415
- tokens.push({ type: "paren", value: "[" });
1416
- index++;
1417
- continue;
1418
- }
1419
- if (ch === "]") {
1420
- tokens.push({ type: "paren", value: "]" });
1421
- index++;
1422
- continue;
1423
- }
1424
- if (ch === ":") {
1425
- tokens.push({ type: "separator", value: ":" });
1426
- index++;
1427
- continue;
1428
- }
1429
- if (ch === ",") {
1430
- tokens.push({ type: "delimiter", value: "," });
1431
- index++;
1432
- continue;
1375
+ // packages/core/src/utils/openaiMessageConversion.ts
1376
+ function asRecord(value) {
1377
+ if (!value || typeof value !== "object") return null;
1378
+ return value;
1379
+ }
1380
+ function convertAnthropicMessagesToOpenAIMessages(messages) {
1381
+ const openaiMessages = [];
1382
+ const toolResults = {};
1383
+ for (const message of messages) {
1384
+ const blocks = [];
1385
+ if (typeof message.message.content === "string") {
1386
+ blocks.push({ type: "text", text: message.message.content });
1387
+ } else if (Array.isArray(message.message.content)) {
1388
+ blocks.push(...message.message.content);
1389
+ } else if (message.message.content) {
1390
+ blocks.push(message.message.content);
1433
1391
  }
1434
- if (ch === '"') {
1435
- let value = "";
1436
- let incomplete = false;
1437
- ch = input[++index];
1438
- while (ch !== '"') {
1439
- if (index === input.length) {
1440
- incomplete = true;
1441
- break;
1442
- }
1443
- if (ch === "\\") {
1444
- if (++index === input.length) {
1445
- incomplete = true;
1446
- break;
1447
- }
1448
- value += ch + input[index];
1449
- ch = input[++index];
1450
- } else {
1451
- value += ch;
1452
- ch = input[++index];
1453
- }
1454
- }
1455
- ch = input[++index];
1456
- if (!incomplete) tokens.push({ type: "string", value });
1457
- continue;
1458
- }
1459
- if (ch && /\s/.test(ch)) {
1460
- index++;
1461
- continue;
1462
- }
1463
- const digit = /[0-9]/;
1464
- if (ch && digit.test(ch) || ch === "-" || ch === ".") {
1465
- let value = "";
1466
- if (ch === "-") {
1467
- value += ch;
1468
- ch = input[++index];
1469
- }
1470
- while (ch && digit.test(ch) || ch === ".") {
1471
- value += ch;
1472
- ch = input[++index];
1473
- }
1474
- tokens.push({ type: "number", value });
1475
- continue;
1476
- }
1477
- const alpha = /[a-z]/i;
1478
- if (ch && alpha.test(ch)) {
1479
- let value = "";
1480
- while (ch && alpha.test(ch)) {
1481
- if (index === input.length) break;
1482
- value += ch;
1483
- ch = input[++index];
1484
- }
1485
- if (value === "true" || value === "false" || value === "null") {
1486
- tokens.push({ type: "name", value });
1487
- } else {
1488
- index++;
1489
- }
1490
- continue;
1491
- }
1492
- index++;
1493
- }
1494
- return tokens;
1495
- }
1496
- function trimTrailingIncompleteTokens(tokens) {
1497
- if (tokens.length === 0) return tokens;
1498
- const last = tokens[tokens.length - 1];
1499
- if (last.type === "separator") {
1500
- return trimTrailingIncompleteTokens(tokens.slice(0, -1));
1501
- }
1502
- if (last.type === "number") {
1503
- const lastChar = last.value[last.value.length - 1];
1504
- if (lastChar === "." || lastChar === "-") {
1505
- return trimTrailingIncompleteTokens(tokens.slice(0, -1));
1506
- }
1507
- }
1508
- if (last.type === "string" || last.type === "number") {
1509
- const previous = tokens[tokens.length - 2];
1510
- if (previous?.type === "delimiter") {
1511
- return trimTrailingIncompleteTokens(tokens.slice(0, -1));
1512
- }
1513
- if (previous?.type === "brace" && previous.value === "{") {
1514
- return trimTrailingIncompleteTokens(tokens.slice(0, -1));
1515
- }
1516
- }
1517
- if (last.type === "delimiter") {
1518
- return trimTrailingIncompleteTokens(tokens.slice(0, -1));
1519
- }
1520
- return tokens;
1521
- }
1522
- function closeOpenBrackets(tokens) {
1523
- const missingClosers = [];
1524
- for (const token of tokens) {
1525
- if (token.type === "brace") {
1526
- if (token.value === "{") missingClosers.push("}");
1527
- else missingClosers.splice(missingClosers.lastIndexOf("}"), 1);
1528
- continue;
1529
- }
1530
- if (token.type === "paren") {
1531
- if (token.value === "[") missingClosers.push("]");
1532
- else missingClosers.splice(missingClosers.lastIndexOf("]"), 1);
1533
- }
1534
- }
1535
- if (missingClosers.length > 0) {
1536
- missingClosers.reverse();
1537
- for (const closer of missingClosers) {
1538
- if (closer === "}") tokens.push({ type: "brace", value: "}" });
1539
- else tokens.push({ type: "paren", value: "]" });
1540
- }
1541
- }
1542
- return tokens;
1543
- }
1544
- function tokensToJson(tokens) {
1545
- let out = "";
1546
- for (const token of tokens) {
1547
- if (token.type === "string") out += `"${token.value}"`;
1548
- else out += token.value;
1549
- }
1550
- return out;
1551
- }
1552
- function parseToolUsePartialJson(input) {
1553
- const tokens = tokenizePartialJson(input);
1554
- const trimmed = trimTrailingIncompleteTokens(tokens);
1555
- const completed = closeOpenBrackets(trimmed);
1556
- return JSON.parse(tokensToJson(completed));
1557
- }
1558
- function parseToolUsePartialJsonOrThrow(input) {
1559
- try {
1560
- return parseToolUsePartialJson(input);
1561
- } catch (error) {
1562
- throw new Error(
1563
- `Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${String(error)}. JSON: ${input}`
1564
- );
1565
- }
1566
- }
1567
-
1568
- // src/utils/model/openaiMessageConversion.ts
1569
- function convertAnthropicMessagesToOpenAIMessages(messages) {
1570
- const openaiMessages = [];
1571
- const toolResults = {};
1572
- for (const message of messages) {
1573
- const blocks = [];
1574
- if (typeof message.message.content === "string") {
1575
- blocks.push({ type: "text", text: message.message.content });
1576
- } else if (Array.isArray(message.message.content)) {
1577
- blocks.push(...message.message.content);
1578
- } else if (message.message.content) {
1579
- blocks.push(message.message.content);
1580
- }
1581
- const role = message.message.role;
1582
- const userContentParts = [];
1583
- const assistantTextParts = [];
1584
- const assistantToolCalls = [];
1585
- for (const block of blocks) {
1586
- if (block.type === "text") {
1587
- const text = typeof block.text === "string" ? block.text : "";
1588
- if (!text) continue;
1589
- if (role === "user") {
1590
- userContentParts.push({ type: "text", text });
1591
- } else if (role === "assistant") {
1592
- assistantTextParts.push(text);
1392
+ const role = message.message.role;
1393
+ const userContentParts = [];
1394
+ const assistantTextParts = [];
1395
+ const assistantToolCalls = [];
1396
+ for (const block of blocks) {
1397
+ if (block.type === "text") {
1398
+ const record = asRecord(block);
1399
+ const text = record && typeof record.text === "string" ? record.text : "";
1400
+ if (!text) continue;
1401
+ if (role === "user") {
1402
+ userContentParts.push({ type: "text", text });
1403
+ } else if (role === "assistant") {
1404
+ assistantTextParts.push(text);
1593
1405
  }
1594
1406
  continue;
1595
1407
  }
@@ -1640,7 +1452,10 @@ function convertAnthropicMessagesToOpenAIMessages(messages) {
1640
1452
  content: userContentParts[0].text
1641
1453
  });
1642
1454
  } else if (userContentParts.length > 0) {
1643
- openaiMessages.push({ role: "user", content: userContentParts });
1455
+ openaiMessages.push({
1456
+ role: "user",
1457
+ content: userContentParts
1458
+ });
1644
1459
  }
1645
1460
  continue;
1646
1461
  }
@@ -1655,14 +1470,17 @@ function convertAnthropicMessagesToOpenAIMessages(messages) {
1655
1470
  continue;
1656
1471
  }
1657
1472
  if (text) {
1658
- openaiMessages.push({ role: "assistant", content: text });
1473
+ openaiMessages.push({
1474
+ role: "assistant",
1475
+ content: text
1476
+ });
1659
1477
  }
1660
1478
  }
1661
1479
  }
1662
1480
  const finalMessages = [];
1663
1481
  for (const message of openaiMessages) {
1664
1482
  finalMessages.push(message);
1665
- if ("tool_calls" in message && message.tool_calls) {
1483
+ if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
1666
1484
  for (const toolCall of message.tool_calls) {
1667
1485
  if (toolResults[toolCall.id]) {
1668
1486
  finalMessages.push(toolResults[toolCall.id]);
@@ -1673,216 +1491,165 @@ function convertAnthropicMessagesToOpenAIMessages(messages) {
1673
1491
  return finalMessages;
1674
1492
  }
1675
1493
 
1676
- // src/services/ai/llm.ts
1677
- function isGPT5Model(modelName) {
1678
- return modelName.startsWith("gpt-5");
1679
- }
1680
- var PROMPT_CACHING_ENABLED = !process.env.DISABLE_PROMPT_CACHING;
1681
- var SONNET_COST_PER_MILLION_INPUT_TOKENS = 3;
1682
- var SONNET_COST_PER_MILLION_OUTPUT_TOKENS = 15;
1683
- var SONNET_COST_PER_MILLION_PROMPT_CACHE_WRITE_TOKENS = 3.75;
1684
- var SONNET_COST_PER_MILLION_PROMPT_CACHE_READ_TOKENS = 0.3;
1685
- var MAX_RETRIES = process.env.USER_TYPE === "SWE_BENCH" ? 100 : 10;
1686
- var BASE_DELAY_MS = 500;
1687
- function abortableDelay(delayMs, signal) {
1688
- return new Promise((resolve, reject) => {
1689
- if (signal?.aborted) {
1690
- reject(new Error("Request was aborted"));
1691
- return;
1692
- }
1693
- const timeoutId = setTimeout(() => {
1694
- resolve();
1695
- }, delayMs);
1696
- if (signal) {
1697
- const abortHandler = () => {
1698
- clearTimeout(timeoutId);
1699
- reject(new Error("Request was aborted"));
1700
- };
1701
- signal.addEventListener("abort", abortHandler, { once: true });
1702
- }
1703
- });
1494
+ // packages/core/src/ai/llm/openai/usage.ts
1495
+ function getMaxTokensFromProfile(modelProfile) {
1496
+ return modelProfile?.maxTokens || 8e3;
1704
1497
  }
1705
- function getRetryDelay(attempt, retryAfterHeader) {
1706
- if (retryAfterHeader) {
1707
- const seconds = parseInt(retryAfterHeader, 10);
1708
- if (!isNaN(seconds)) {
1709
- return seconds * 1e3;
1710
- }
1498
+ function normalizeUsage(usage) {
1499
+ if (!usage) {
1500
+ return {
1501
+ input_tokens: 0,
1502
+ output_tokens: 0,
1503
+ cache_read_input_tokens: 0,
1504
+ cache_creation_input_tokens: 0
1505
+ };
1711
1506
  }
1712
- return Math.min(BASE_DELAY_MS * Math.pow(2, attempt - 1), 32e3);
1507
+ return {
1508
+ input_tokens: usage.input_tokens ?? usage.prompt_tokens ?? usage.promptTokens ?? usage.inputTokens ?? 0,
1509
+ output_tokens: usage.output_tokens ?? usage.completion_tokens ?? usage.completionTokens ?? usage.outputTokens ?? 0,
1510
+ cache_read_input_tokens: usage.cache_read_input_tokens ?? 0,
1511
+ cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0,
1512
+ prompt_tokens: usage.prompt_tokens ?? usage.input_tokens ?? usage.promptTokens ?? 0,
1513
+ completion_tokens: usage.completion_tokens ?? usage.output_tokens ?? usage.completionTokens ?? 0,
1514
+ promptTokens: usage.promptTokens ?? usage.prompt_tokens ?? usage.input_tokens ?? 0,
1515
+ completionTokens: usage.completionTokens ?? usage.completion_tokens ?? usage.output_tokens ?? 0,
1516
+ totalTokens: usage.totalTokens ?? (usage.prompt_tokens ?? usage.input_tokens ?? usage.promptTokens ?? 0) + (usage.completion_tokens ?? usage.output_tokens ?? usage.completionTokens ?? 0),
1517
+ reasoningTokens: usage.reasoningTokens
1518
+ };
1713
1519
  }
1714
- function shouldRetry(error) {
1715
- if (error.message?.includes('"type":"overloaded_error"')) {
1716
- return process.env.USER_TYPE === "SWE_BENCH";
1717
- }
1718
- const shouldRetryHeader = error.headers?.["x-should-retry"];
1719
- if (shouldRetryHeader === "true") return true;
1720
- if (shouldRetryHeader === "false") return false;
1721
- if (error instanceof APIConnectionError) {
1722
- return true;
1520
+
1521
+ // packages/core/src/ai/llm/openai/conversion.ts
1522
+ function mapFinishReasonToStopReason(reason) {
1523
+ switch (reason) {
1524
+ case "stop":
1525
+ return "end_turn";
1526
+ case "length":
1527
+ return "max_tokens";
1528
+ case "tool_calls":
1529
+ case "function_call":
1530
+ return "tool_use";
1531
+ default:
1532
+ return null;
1723
1533
  }
1724
- if (!error.status) return false;
1725
- if (error.status === 408) return true;
1726
- if (error.status === 409) return true;
1727
- if (error.status === 429) return true;
1728
- if (error.status && error.status >= 500) return true;
1729
- return false;
1730
1534
  }
1731
- async function withRetry(operation, options = {}) {
1732
- const maxRetries = options.maxRetries ?? MAX_RETRIES;
1733
- let lastError;
1734
- for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
1735
- try {
1736
- return await operation(attempt);
1737
- } catch (error) {
1738
- lastError = error;
1739
- if (attempt > maxRetries || !(error instanceof APIError) || !shouldRetry(error)) {
1740
- throw error;
1741
- }
1742
- if (options.signal?.aborted) {
1743
- throw new Error("Request cancelled by user");
1535
+ function convertAnthropicMessagesToOpenAIMessages2(messages) {
1536
+ return convertAnthropicMessagesToOpenAIMessages(messages);
1537
+ }
1538
+ function convertOpenAIResponseToAnthropic(response, tools) {
1539
+ const normalizedUsage = normalizeUsage(response.usage);
1540
+ let contentBlocks = [];
1541
+ const message = response.choices?.[0]?.message;
1542
+ if (!message) {
1543
+ return {
1544
+ id: nanoid(),
1545
+ model: response.model ?? "<openai>",
1546
+ role: "assistant",
1547
+ content: [],
1548
+ stop_reason: mapFinishReasonToStopReason(
1549
+ response.choices?.[0]?.finish_reason
1550
+ ),
1551
+ stop_sequence: null,
1552
+ type: "message",
1553
+ usage: {
1554
+ input_tokens: normalizedUsage.input_tokens ?? 0,
1555
+ output_tokens: normalizedUsage.output_tokens ?? 0,
1556
+ cache_creation_input_tokens: normalizedUsage.cache_creation_input_tokens ?? 0,
1557
+ cache_read_input_tokens: normalizedUsage.cache_read_input_tokens ?? 0
1744
1558
  }
1745
- const retryAfter = error.headers?.["retry-after"] ?? null;
1746
- const delayMs = getRetryDelay(attempt, retryAfter);
1747
- debug.warn("LLM_API_RETRY", {
1748
- name: error.name,
1749
- message: error.message,
1750
- status: error.status,
1751
- attempt,
1752
- maxRetries,
1753
- delayMs
1754
- });
1559
+ };
1560
+ }
1561
+ if (message?.tool_calls) {
1562
+ for (const toolCall of message.tool_calls) {
1563
+ const tool = toolCall.function;
1564
+ const toolName = tool.name;
1565
+ let toolArgs = {};
1755
1566
  try {
1756
- await abortableDelay(delayMs, options.signal);
1757
- } catch (delayError) {
1758
- if (delayError.message === "Request was aborted") {
1759
- throw new Error("Request cancelled by user");
1760
- }
1761
- throw delayError;
1567
+ toolArgs = tool.arguments ? JSON.parse(tool.arguments) : {};
1568
+ } catch (e) {
1762
1569
  }
1570
+ contentBlocks.push({
1571
+ type: "tool_use",
1572
+ input: toolArgs,
1573
+ name: toolName,
1574
+ id: toolCall.id?.length > 0 ? toolCall.id : nanoid()
1575
+ });
1763
1576
  }
1764
1577
  }
1765
- throw lastError;
1766
- }
1767
- async function fetchAnthropicModels(baseURL, apiKey) {
1768
- try {
1769
- const modelsURL = baseURL ? `${baseURL.replace(/\/+$/, "")}/v1/models` : "https://api.anthropic.com/v1/models";
1770
- const response = await fetch(modelsURL, {
1771
- method: "GET",
1772
- headers: {
1773
- "x-api-key": apiKey,
1774
- "anthropic-version": "2023-06-01",
1775
- "User-Agent": USER_AGENT
1776
- }
1777
- });
1778
- if (!response.ok) {
1779
- if (response.status === 401) {
1780
- throw new Error(
1781
- "Invalid API key. Please check your Anthropic API key and try again."
1782
- );
1783
- } else if (response.status === 403) {
1784
- throw new Error(
1785
- "API key does not have permission to access models. Please check your API key permissions."
1786
- );
1787
- } else if (response.status === 429) {
1788
- throw new Error(
1789
- "Too many requests. Please wait a moment and try again."
1790
- );
1791
- } else if (response.status >= 500) {
1792
- throw new Error(
1793
- "Anthropic service is temporarily unavailable. Please try again later."
1794
- );
1795
- } else {
1796
- throw new Error(
1797
- `Unable to connect to Anthropic API (${response.status}). Please check your internet connection and API key.`
1798
- );
1799
- }
1800
- }
1801
- const data = await response.json();
1802
- return data.data || [];
1803
- } catch (error) {
1804
- if (error instanceof Error && error.message.includes("API key") || error instanceof Error && error.message.includes("Anthropic")) {
1805
- throw error;
1806
- }
1807
- logError(error);
1808
- debug.warn("ANTHROPIC_MODELS_FETCH_FAILED", {
1809
- error: error instanceof Error ? error.message : String(error)
1578
+ const record = message;
1579
+ if (typeof record.reasoning === "string" && record.reasoning) {
1580
+ contentBlocks.push({
1581
+ type: "thinking",
1582
+ thinking: record.reasoning,
1583
+ signature: ""
1810
1584
  });
1811
- throw new Error(
1812
- "Unable to connect to Anthropic API. Please check your internet connection and try again."
1813
- );
1814
1585
  }
1815
- }
1816
- async function verifyApiKey(apiKey, baseURL, provider) {
1817
- if (!apiKey) {
1818
- return false;
1586
+ if (typeof record.reasoning_content === "string" && record.reasoning_content) {
1587
+ contentBlocks.push({
1588
+ type: "thinking",
1589
+ thinking: record.reasoning_content,
1590
+ signature: ""
1591
+ });
1819
1592
  }
1820
- if (provider && provider !== "anthropic") {
1821
- try {
1822
- const headers = {
1823
- Authorization: `Bearer ${apiKey}`,
1824
- "Content-Type": "application/json"
1825
- };
1826
- if (!baseURL) {
1827
- debug.warn("API_VERIFICATION_MISSING_BASE_URL", { provider });
1828
- return false;
1829
- }
1830
- const modelsURL = `${baseURL.replace(/\/+$/, "")}/models`;
1831
- const response = await fetch(modelsURL, {
1832
- method: "GET",
1833
- headers
1834
- });
1835
- return response.ok;
1836
- } catch (error) {
1837
- logError(error);
1838
- debug.warn("API_VERIFICATION_FAILED", {
1839
- provider,
1840
- error: error instanceof Error ? error.message : String(error)
1841
- });
1842
- return false;
1843
- }
1593
+ if (message.content) {
1594
+ contentBlocks.push({
1595
+ type: "text",
1596
+ text: message.content,
1597
+ citations: []
1598
+ });
1844
1599
  }
1845
- const clientConfig = {
1846
- apiKey,
1847
- dangerouslyAllowBrowser: true,
1848
- maxRetries: 3,
1849
- defaultHeaders: {
1850
- "User-Agent": USER_AGENT
1600
+ const finalMessage = {
1601
+ id: nanoid(),
1602
+ model: response.model ?? "<openai>",
1603
+ role: "assistant",
1604
+ content: contentBlocks,
1605
+ stop_reason: mapFinishReasonToStopReason(
1606
+ response.choices?.[0]?.finish_reason
1607
+ ),
1608
+ stop_sequence: null,
1609
+ type: "message",
1610
+ usage: {
1611
+ input_tokens: normalizedUsage.input_tokens ?? 0,
1612
+ output_tokens: normalizedUsage.output_tokens ?? 0,
1613
+ cache_creation_input_tokens: normalizedUsage.cache_creation_input_tokens ?? 0,
1614
+ cache_read_input_tokens: normalizedUsage.cache_read_input_tokens ?? 0
1851
1615
  }
1852
1616
  };
1853
- if (baseURL && (provider === "anthropic" || provider === "minimax-coding")) {
1854
- clientConfig.baseURL = baseURL;
1617
+ return finalMessage;
1618
+ }
1619
+
1620
+ // packages/core/src/ai/llm/openai/params.ts
1621
+ function isGPT5Model(modelName) {
1622
+ return modelName.startsWith("gpt-5");
1623
+ }
1624
+ function buildOpenAIChatCompletionCreateParams(args) {
1625
+ const isGPT5 = isGPT5Model(args.model);
1626
+ const opts = {
1627
+ model: args.model,
1628
+ ...isGPT5 ? { max_completion_tokens: args.maxTokens } : { max_tokens: args.maxTokens },
1629
+ messages: args.messages,
1630
+ temperature: args.temperature
1631
+ };
1632
+ if (args.stopSequences && args.stopSequences.length > 0) {
1633
+ opts.stop = args.stopSequences;
1634
+ }
1635
+ if (args.stream) {
1636
+ ;
1637
+ opts.stream = true;
1638
+ opts.stream_options = {
1639
+ include_usage: true
1640
+ };
1855
1641
  }
1856
- const anthropic = new Anthropic(clientConfig);
1857
- try {
1858
- await withRetry(
1859
- async () => {
1860
- const model = "claude-sonnet-4-20250514";
1861
- const messages = [{ role: "user", content: "test" }];
1862
- await anthropic.messages.create({
1863
- model,
1864
- max_tokens: 1e3,
1865
- messages,
1866
- temperature: 0
1867
- });
1868
- return true;
1869
- },
1870
- { maxRetries: 2 }
1871
- );
1872
- return true;
1873
- } catch (error) {
1874
- logError(error);
1875
- if (error instanceof Error && error.message.includes(
1876
- '{"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"}}'
1877
- )) {
1878
- return false;
1879
- }
1880
- throw error;
1642
+ if (args.toolSchemas.length > 0) {
1643
+ opts.tools = args.toolSchemas;
1644
+ opts.tool_choice = "auto";
1881
1645
  }
1646
+ if (args.reasoningEffort) {
1647
+ opts.reasoning_effort = args.reasoningEffort;
1648
+ }
1649
+ return opts;
1882
1650
  }
1883
- function convertAnthropicMessagesToOpenAIMessages2(messages) {
1884
- return convertAnthropicMessagesToOpenAIMessages(messages);
1885
- }
1651
+
1652
+ // packages/core/src/ai/llm/openai/stream.ts
1886
1653
  function messageReducer(previous, item) {
1887
1654
  const reduce = (acc, delta) => {
1888
1655
  acc = { ...acc };
@@ -2016,20 +1783,14 @@ async function handleMessageStream(stream, signal) {
2016
1783
  usage
2017
1784
  };
2018
1785
  }
2019
- function convertOpenAIResponseToAnthropic(response, tools) {
2020
- let contentBlocks = [];
2021
- const message = response.choices?.[0]?.message;
2022
- if (!message) {
2023
- return {
2024
- role: "assistant",
2025
- content: [],
2026
- stop_reason: response.choices?.[0]?.finish_reason,
2027
- type: "message",
2028
- usage: response.usage
2029
- };
2030
- }
2031
- if (message?.tool_calls) {
2032
- for (const toolCall of message.tool_calls) {
1786
+
1787
+ // packages/core/src/ai/llm/openai/unifiedResponse.ts
1788
+ import { nanoid as nanoid2 } from "nanoid";
1789
+ import { randomUUID as randomUUID2 } from "crypto";
1790
+ function buildAssistantMessageFromUnifiedResponse(unifiedResponse, startTime) {
1791
+ const contentBlocks = [...unifiedResponse.content || []];
1792
+ if (unifiedResponse.toolCalls && unifiedResponse.toolCalls.length > 0) {
1793
+ for (const toolCall of unifiedResponse.toolCalls) {
2033
1794
  const tool = toolCall.function;
2034
1795
  const toolName = tool?.name;
2035
1796
  let toolArgs = {};
@@ -2041,73 +1802,333 @@ function convertOpenAIResponseToAnthropic(response, tools) {
2041
1802
  type: "tool_use",
2042
1803
  input: toolArgs,
2043
1804
  name: toolName,
2044
- id: toolCall.id?.length > 0 ? toolCall.id : nanoid()
1805
+ id: toolCall.id?.length > 0 ? toolCall.id : nanoid2()
2045
1806
  });
2046
1807
  }
2047
1808
  }
2048
- if (message.reasoning) {
2049
- contentBlocks.push({
2050
- type: "thinking",
2051
- thinking: message.reasoning,
2052
- signature: ""
2053
- });
2054
- }
2055
- if (message.reasoning_content) {
2056
- contentBlocks.push({
2057
- type: "thinking",
2058
- thinking: message.reasoning_content,
2059
- signature: ""
2060
- });
2061
- }
2062
- if (message.content) {
2063
- contentBlocks.push({
2064
- type: "text",
2065
- text: message?.content,
2066
- citations: []
2067
- });
2068
- }
2069
- const finalMessage = {
2070
- role: "assistant",
2071
- content: contentBlocks,
2072
- stop_reason: response.choices?.[0]?.finish_reason,
2073
- type: "message",
2074
- usage: response.usage
1809
+ const inputTokens = unifiedResponse.usage?.promptTokens ?? unifiedResponse.usage?.input_tokens ?? 0;
1810
+ const outputTokens = unifiedResponse.usage?.completionTokens ?? unifiedResponse.usage?.output_tokens ?? 0;
1811
+ return {
1812
+ type: "assistant",
1813
+ message: {
1814
+ id: unifiedResponse.responseId ?? nanoid2(),
1815
+ model: unifiedResponse.model ?? "",
1816
+ role: "assistant",
1817
+ type: "message",
1818
+ stop_reason: unifiedResponse.stopReason ?? null,
1819
+ stop_sequence: null,
1820
+ content: contentBlocks,
1821
+ usage: {
1822
+ input_tokens: inputTokens,
1823
+ output_tokens: outputTokens,
1824
+ cache_creation_input_tokens: 0,
1825
+ cache_read_input_tokens: 0
1826
+ }
1827
+ },
1828
+ costUSD: 0,
1829
+ durationMs: Date.now() - startTime,
1830
+ uuid: randomUUID2(),
1831
+ responseId: unifiedResponse.responseId
2075
1832
  };
2076
- return finalMessage;
2077
1833
  }
2078
- var anthropicClient = null;
2079
- function getAnthropicClient(model) {
1834
+
1835
+ // packages/core/src/ai/llm/openai/queryOpenAI.ts
1836
+ var SONNET_COST_PER_MILLION_INPUT_TOKENS = 3;
1837
+ var SONNET_COST_PER_MILLION_OUTPUT_TOKENS = 15;
1838
+ var SONNET_COST_PER_MILLION_PROMPT_CACHE_WRITE_TOKENS = 3.75;
1839
+ var SONNET_COST_PER_MILLION_PROMPT_CACHE_READ_TOKENS = 0.3;
1840
+ async function queryOpenAI(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
2080
1841
  const config = getGlobalConfig();
2081
- const provider = config.primaryProvider;
2082
- if (anthropicClient && provider) {
2083
- anthropicClient = null;
2084
- }
2085
- if (anthropicClient) {
2086
- return anthropicClient;
2087
- }
2088
- const region = getVertexRegionForModel(model);
2089
1842
  const modelManager = getModelManager();
2090
- const modelProfile = modelManager.getModel("main");
2091
- const defaultHeaders = {
2092
- "x-app": "cli",
2093
- "User-Agent": USER_AGENT
2094
- };
2095
- if (process.env.ANTHROPIC_AUTH_TOKEN) {
2096
- defaultHeaders["Authorization"] = `Bearer ${process.env.ANTHROPIC_AUTH_TOKEN}`;
1843
+ const toolUseContext = options?.toolUseContext;
1844
+ const modelProfile = options?.modelProfile || modelManager.getModel("main");
1845
+ let model;
1846
+ const currentRequest = getCurrentRequest();
1847
+ debug.api("MODEL_CONFIG_OPENAI", {
1848
+ modelProfileFound: !!modelProfile,
1849
+ modelProfileId: modelProfile?.modelName,
1850
+ modelProfileName: modelProfile?.name,
1851
+ modelProfileModelName: modelProfile?.modelName,
1852
+ modelProfileProvider: modelProfile?.provider,
1853
+ modelProfileBaseURL: modelProfile?.baseURL,
1854
+ modelProfileApiKeyExists: !!modelProfile?.apiKey,
1855
+ optionsModel: options?.model,
1856
+ requestId: getCurrentRequest()?.id
1857
+ });
1858
+ if (modelProfile) {
1859
+ model = modelProfile.modelName;
1860
+ } else {
1861
+ model = options?.model || modelProfile?.modelName || "";
2097
1862
  }
2098
- const ARGS = {
2099
- defaultHeaders,
2100
- maxRetries: 0,
2101
- timeout: parseInt(process.env.API_TIMEOUT_MS || String(60 * 1e3), 10)
2102
- };
2103
- if (USE_BEDROCK) {
2104
- const client = new AnthropicBedrock(ARGS);
2105
- anthropicClient = client;
2106
- return client;
1863
+ if (options?.prependCLISysprompt) {
1864
+ const [firstSyspromptBlock] = splitSysPromptPrefix(systemPrompt);
1865
+ systemPrompt = [getCLISyspromptPrefix() + systemPrompt];
2107
1866
  }
2108
- if (USE_VERTEX) {
2109
- const vertexArgs = {
2110
- ...ARGS,
1867
+ const system = splitSysPromptPrefix(systemPrompt).map(
1868
+ (_) => ({
1869
+ ...PROMPT_CACHING_ENABLED ? { cache_control: { type: "ephemeral" } } : {},
1870
+ text: _,
1871
+ type: "text"
1872
+ })
1873
+ );
1874
+ const toolSchemas = await Promise.all(
1875
+ tools.map(
1876
+ async (_) => ({
1877
+ type: "function",
1878
+ function: {
1879
+ name: _.name,
1880
+ description: await _.prompt({
1881
+ safeMode: options?.safeMode
1882
+ }),
1883
+ // Use tool's JSON schema directly if provided, otherwise convert Zod schema
1884
+ parameters: "inputJSONSchema" in _ && _.inputJSONSchema ? _.inputJSONSchema : zodToJsonSchema4(_.inputSchema)
1885
+ }
1886
+ })
1887
+ )
1888
+ );
1889
+ const openaiSystem = system.map(
1890
+ (s) => ({
1891
+ role: "system",
1892
+ content: s.text
1893
+ })
1894
+ );
1895
+ const openaiMessages = convertAnthropicMessagesToOpenAIMessages2(messages);
1896
+ logSystemPromptConstruction({
1897
+ basePrompt: systemPrompt.join("\n"),
1898
+ kodeContext: generateKodeContext() || "",
1899
+ reminders: [],
1900
+ // 这里可以从 generateSystemReminders 获取
1901
+ finalPrompt: systemPrompt.join("\n")
1902
+ });
1903
+ let start = Date.now();
1904
+ let adapterContext = null;
1905
+ if (modelProfile && modelProfile.modelName) {
1906
+ debug.api("CHECKING_ADAPTER_SYSTEM", {
1907
+ modelProfileName: modelProfile.modelName,
1908
+ modelName: modelProfile.modelName,
1909
+ provider: modelProfile.provider,
1910
+ requestId: getCurrentRequest()?.id
1911
+ });
1912
+ const USE_NEW_ADAPTER_SYSTEM = process.env.USE_NEW_ADAPTERS !== "false";
1913
+ if (USE_NEW_ADAPTER_SYSTEM) {
1914
+ const shouldUseResponses = ModelAdapterFactory.shouldUseResponsesAPI(modelProfile);
1915
+ if (shouldUseResponses) {
1916
+ const adapter = ModelAdapterFactory.createAdapter(modelProfile);
1917
+ const reasoningEffort = await getReasoningEffort(modelProfile, messages);
1918
+ let verbosity = "medium";
1919
+ const modelNameLower = modelProfile.modelName.toLowerCase();
1920
+ if (modelNameLower.includes("high")) {
1921
+ verbosity = "high";
1922
+ } else if (modelNameLower.includes("low")) {
1923
+ verbosity = "low";
1924
+ }
1925
+ const unifiedParams = {
1926
+ messages: openaiMessages,
1927
+ systemPrompt: openaiSystem.map((s) => s.content),
1928
+ tools,
1929
+ maxTokens: options?.maxTokens ?? getMaxTokensFromProfile(modelProfile),
1930
+ stream: config.stream,
1931
+ reasoningEffort: reasoningEffort ?? void 0,
1932
+ temperature: options?.temperature ?? (isGPT5Model(model) ? 1 : MAIN_QUERY_TEMPERATURE),
1933
+ previousResponseId: toolUseContext?.responseState?.previousResponseId,
1934
+ verbosity,
1935
+ ...options?.stopSequences && options.stopSequences.length > 0 ? { stopSequences: options.stopSequences } : {}
1936
+ };
1937
+ adapterContext = {
1938
+ adapter,
1939
+ request: adapter.createRequest(unifiedParams),
1940
+ shouldUseResponses: true
1941
+ };
1942
+ }
1943
+ }
1944
+ }
1945
+ let queryResult;
1946
+ let startIncludingRetries = Date.now();
1947
+ try {
1948
+ queryResult = await withRetry(
1949
+ async () => {
1950
+ start = Date.now();
1951
+ if (adapterContext) {
1952
+ if (adapterContext.shouldUseResponses) {
1953
+ const { callGPT5ResponsesAPI } = await import("./openai-XXK3YZG4.js");
1954
+ const response = await callGPT5ResponsesAPI(
1955
+ modelProfile,
1956
+ adapterContext.request,
1957
+ signal
1958
+ );
1959
+ const unifiedResponse = await adapterContext.adapter.parseResponse(response);
1960
+ const assistantMessage2 = buildAssistantMessageFromUnifiedResponse(
1961
+ unifiedResponse,
1962
+ start
1963
+ );
1964
+ assistantMessage2.message.usage = normalizeUsage(
1965
+ assistantMessage2.message.usage
1966
+ );
1967
+ return {
1968
+ assistantMessage: assistantMessage2,
1969
+ rawResponse: unifiedResponse,
1970
+ apiFormat: "openai"
1971
+ };
1972
+ }
1973
+ const s2 = await getCompletionWithProfile(
1974
+ modelProfile,
1975
+ adapterContext.request,
1976
+ 0,
1977
+ 10,
1978
+ signal
1979
+ );
1980
+ let finalResponse2;
1981
+ if (config.stream) {
1982
+ finalResponse2 = await handleMessageStream(
1983
+ s2,
1984
+ signal
1985
+ );
1986
+ } else {
1987
+ finalResponse2 = s2;
1988
+ }
1989
+ const message2 = convertOpenAIResponseToAnthropic(finalResponse2, tools);
1990
+ const assistantMsg2 = {
1991
+ type: "assistant",
1992
+ message: message2,
1993
+ costUSD: 0,
1994
+ durationMs: Date.now() - start,
1995
+ uuid: randomUUID3()
1996
+ };
1997
+ return {
1998
+ assistantMessage: assistantMsg2,
1999
+ rawResponse: finalResponse2,
2000
+ apiFormat: "openai"
2001
+ };
2002
+ }
2003
+ const maxTokens = options?.maxTokens ?? getMaxTokensFromProfile(modelProfile);
2004
+ const opts = buildOpenAIChatCompletionCreateParams({
2005
+ model,
2006
+ maxTokens,
2007
+ messages: [...openaiSystem, ...openaiMessages],
2008
+ temperature: options?.temperature ?? (isGPT5Model(model) ? 1 : MAIN_QUERY_TEMPERATURE),
2009
+ stream: config.stream,
2010
+ toolSchemas,
2011
+ stopSequences: options?.stopSequences,
2012
+ reasoningEffort: await getReasoningEffort(modelProfile, messages)
2013
+ });
2014
+ const completionFunction = isGPT5Model(modelProfile?.modelName || "") ? getGPT5CompletionWithProfile : getCompletionWithProfile;
2015
+ const s = await completionFunction(modelProfile, opts, 0, 10, signal);
2016
+ let finalResponse;
2017
+ if (opts.stream) {
2018
+ finalResponse = await handleMessageStream(
2019
+ s,
2020
+ signal
2021
+ );
2022
+ } else {
2023
+ finalResponse = s;
2024
+ }
2025
+ const message = convertOpenAIResponseToAnthropic(finalResponse, tools);
2026
+ const assistantMsg = {
2027
+ type: "assistant",
2028
+ message,
2029
+ costUSD: 0,
2030
+ durationMs: Date.now() - start,
2031
+ uuid: randomUUID3()
2032
+ };
2033
+ return {
2034
+ assistantMessage: assistantMsg,
2035
+ rawResponse: finalResponse,
2036
+ apiFormat: "openai"
2037
+ };
2038
+ },
2039
+ { signal }
2040
+ );
2041
+ } catch (error) {
2042
+ logError(error);
2043
+ return getAssistantMessageFromError(error);
2044
+ }
2045
+ const durationMs = Date.now() - start;
2046
+ const durationMsIncludingRetries = Date.now() - startIncludingRetries;
2047
+ const assistantMessage = queryResult.assistantMessage;
2048
+ assistantMessage.message.content = normalizeContentFromAPI(
2049
+ assistantMessage.message.content || []
2050
+ );
2051
+ const normalizedUsage = normalizeUsage(assistantMessage.message.usage);
2052
+ assistantMessage.message.usage = normalizedUsage;
2053
+ const inputTokens = normalizedUsage.input_tokens ?? 0;
2054
+ const outputTokens = normalizedUsage.output_tokens ?? 0;
2055
+ const cacheReadInputTokens = normalizedUsage.cache_read_input_tokens ?? 0;
2056
+ const cacheCreationInputTokens = normalizedUsage.cache_creation_input_tokens ?? 0;
2057
+ const costUSD = inputTokens / 1e6 * SONNET_COST_PER_MILLION_INPUT_TOKENS + outputTokens / 1e6 * SONNET_COST_PER_MILLION_OUTPUT_TOKENS + cacheReadInputTokens / 1e6 * SONNET_COST_PER_MILLION_PROMPT_CACHE_READ_TOKENS + cacheCreationInputTokens / 1e6 * SONNET_COST_PER_MILLION_PROMPT_CACHE_WRITE_TOKENS;
2058
+ addToTotalCost(costUSD, durationMsIncludingRetries);
2059
+ logLLMInteraction({
2060
+ systemPrompt: systemPrompt.join("\n"),
2061
+ messages: [...openaiSystem, ...openaiMessages],
2062
+ response: assistantMessage.message || queryResult.rawResponse,
2063
+ usage: {
2064
+ inputTokens,
2065
+ outputTokens
2066
+ },
2067
+ timing: {
2068
+ start,
2069
+ end: Date.now()
2070
+ },
2071
+ apiFormat: queryResult.apiFormat
2072
+ });
2073
+ assistantMessage.costUSD = costUSD;
2074
+ assistantMessage.durationMs = durationMs;
2075
+ assistantMessage.uuid = assistantMessage.uuid || randomUUID3();
2076
+ return assistantMessage;
2077
+ }
2078
+
2079
+ // packages/core/src/ai/llm/anthropic/native.ts
2080
+ import Anthropic2 from "@anthropic-ai/sdk";
2081
+ import { nanoid as nanoid3 } from "nanoid";
2082
+ import { zodToJsonSchema as zodToJsonSchema5 } from "zod-to-json-schema";
2083
+
2084
+ // packages/core/src/utils/http.ts
2085
+ var USER_AGENT = `${PRODUCT_COMMAND}/${MACRO.VERSION} (${process.env.USER_TYPE})`;
2086
+
2087
+ // packages/core/src/ai/llm/maxTokens.ts
2088
+ function getMaxTokensFromProfile2(modelProfile) {
2089
+ return modelProfile?.maxTokens || 8e3;
2090
+ }
2091
+
2092
+ // packages/core/src/ai/llm/anthropic/client.ts
2093
+ import "@anthropic-ai/sdk/shims/node";
2094
+ import Anthropic from "@anthropic-ai/sdk";
2095
+ import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
2096
+ import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";
2097
+ import chalk from "chalk";
2098
+ var anthropicClient = null;
2099
+ function getAnthropicClient(model) {
2100
+ const config = getGlobalConfig();
2101
+ const provider = config.primaryProvider;
2102
+ if (anthropicClient && provider) {
2103
+ anthropicClient = null;
2104
+ }
2105
+ if (anthropicClient) {
2106
+ return anthropicClient;
2107
+ }
2108
+ const region = getVertexRegionForModel(model);
2109
+ const modelManager = getModelManager();
2110
+ const modelProfile = modelManager.getModel("main");
2111
+ const defaultHeaders = {
2112
+ "x-app": "cli",
2113
+ "User-Agent": USER_AGENT
2114
+ };
2115
+ if (process.env.ANTHROPIC_AUTH_TOKEN) {
2116
+ defaultHeaders["Authorization"] = `Bearer ${process.env.ANTHROPIC_AUTH_TOKEN}`;
2117
+ }
2118
+ const ARGS = {
2119
+ defaultHeaders,
2120
+ maxRetries: 0,
2121
+ // Disabled auto-retry in favor of manual implementation
2122
+ timeout: parseInt(process.env.API_TIMEOUT_MS || String(60 * 1e3), 10)
2123
+ };
2124
+ if (USE_BEDROCK) {
2125
+ const client = new AnthropicBedrock(ARGS);
2126
+ anthropicClient = client;
2127
+ return client;
2128
+ }
2129
+ if (USE_VERTEX) {
2130
+ const vertexArgs = {
2131
+ ...ARGS,
2111
2132
  region: region || process.env.CLOUD_ML_REGION || "us-east5"
2112
2133
  };
2113
2134
  const client = new AnthropicVertex(vertexArgs);
@@ -2135,6 +2156,7 @@ function getAnthropicClient(model) {
2135
2156
  dangerouslyAllowBrowser: true,
2136
2157
  ...ARGS,
2137
2158
  ...baseURL && { baseURL }
2159
+ // Use baseURL directly, SDK will handle API versioning
2138
2160
  };
2139
2161
  anthropicClient = new Anthropic(clientConfig);
2140
2162
  return anthropicClient;
@@ -2142,13 +2164,15 @@ function getAnthropicClient(model) {
2142
2164
  function resetAnthropicClient() {
2143
2165
  anthropicClient = null;
2144
2166
  }
2167
+
2168
+ // packages/core/src/ai/llm/anthropic/cacheControl.ts
2145
2169
  function applyCacheControlWithLimits(systemBlocks, messageParams) {
2146
2170
  if (!PROMPT_CACHING_ENABLED) {
2147
2171
  return { systemBlocks, messageParams };
2148
2172
  }
2149
2173
  const maxCacheBlocks = 4;
2150
2174
  let usedCacheBlocks = 0;
2151
- const processedSystemBlocks = systemBlocks.map((block, index) => {
2175
+ const processedSystemBlocks = systemBlocks.map((block) => {
2152
2176
  if (usedCacheBlocks < maxCacheBlocks && block.text.length > 1e3) {
2153
2177
  usedCacheBlocks++;
2154
2178
  return {
@@ -2163,7 +2187,9 @@ function applyCacheControlWithLimits(systemBlocks, messageParams) {
2163
2187
  if (Array.isArray(message.content)) {
2164
2188
  const processedContent = message.content.map(
2165
2189
  (contentBlock, blockIndex) => {
2166
- const shouldCache = usedCacheBlocks < maxCacheBlocks && contentBlock.type === "text" && typeof contentBlock.text === "string" && (contentBlock.text.length > 2e3 || messageIndex === messageParams.length - 1 && blockIndex === message.content.length - 1 && contentBlock.text.length > 500);
2190
+ const shouldCache = usedCacheBlocks < maxCacheBlocks && contentBlock.type === "text" && typeof contentBlock.text === "string" && // Long documents (over 2000 characters)
2191
+ (contentBlock.text.length > 2e3 || // Last content block of the last message (may be important context)
2192
+ messageIndex === messageParams.length - 1 && blockIndex === message.content.length - 1 && contentBlock.text.length > 500);
2167
2193
  if (shouldCache) {
2168
2194
  usedCacheBlocks++;
2169
2195
  return {
@@ -2171,8 +2197,10 @@ function applyCacheControlWithLimits(systemBlocks, messageParams) {
2171
2197
  cache_control: { type: "ephemeral" }
2172
2198
  };
2173
2199
  }
2174
- const { cache_control, ...blockWithoutCache } = contentBlock;
2175
- return blockWithoutCache;
2200
+ if ("cache_control" in contentBlock) {
2201
+ return { ...contentBlock, cache_control: void 0 };
2202
+ }
2203
+ return contentBlock;
2176
2204
  }
2177
2205
  );
2178
2206
  return {
@@ -2187,6 +2215,8 @@ function applyCacheControlWithLimits(systemBlocks, messageParams) {
2187
2215
  messageParams: processedMessageParams
2188
2216
  };
2189
2217
  }
2218
+
2219
+ // packages/core/src/ai/llm/anthropic/messageParams.ts
2190
2220
  function userMessageToMessageParam(message, addCache = false) {
2191
2221
  if (addCache) {
2192
2222
  if (typeof message.message.content === "string") {
@@ -2235,157 +2265,351 @@ function assistantMessageToMessageParam(message, addCache = false) {
2235
2265
  content: message.message.content
2236
2266
  };
2237
2267
  }
2238
- function splitSysPromptPrefix(systemPrompt) {
2239
- const systemPromptFirstBlock = systemPrompt[0] || "";
2240
- const systemPromptRest = systemPrompt.slice(1);
2241
- return [systemPromptFirstBlock, systemPromptRest.join("\n")].filter(Boolean);
2268
+ function addCacheBreakpoints(messages) {
2269
+ return messages.map((msg, index) => {
2270
+ return msg.type === "user" ? userMessageToMessageParam(msg, index > messages.length - 3) : assistantMessageToMessageParam(msg, index > messages.length - 3);
2271
+ });
2242
2272
  }
2243
- async function queryLLM(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
2244
- const modelManager = options.__testModelManager ?? getModelManager();
2245
- const modelResolution = modelManager.resolveModelWithInfo(options.model);
2246
- if (!modelResolution.success || !modelResolution.profile) {
2247
- const fallbackProfile = modelManager.resolveModel(options.model);
2248
- if (!fallbackProfile) {
2249
- throw new Error(
2250
- modelResolution.error || `Failed to resolve model: ${options.model}`
2251
- );
2273
+
2274
+ // packages/core/src/utils/toolUsePartialJson.ts
2275
+ function tokenizePartialJson(input) {
2276
+ let index = 0;
2277
+ const tokens = [];
2278
+ while (index < input.length) {
2279
+ let ch = input[index];
2280
+ if (ch === "\\") {
2281
+ index++;
2282
+ continue;
2252
2283
  }
2253
- debug.warn("MODEL_RESOLUTION_FALLBACK", {
2254
- inputParam: options.model,
2255
- error: modelResolution.error,
2256
- fallbackModelName: fallbackProfile.modelName,
2257
- fallbackProvider: fallbackProfile.provider,
2258
- requestId: getCurrentRequest()?.id
2259
- });
2260
- modelResolution.success = true;
2261
- modelResolution.profile = fallbackProfile;
2262
- }
2263
- const modelProfile = modelResolution.profile;
2264
- const resolvedModel = modelProfile.modelName;
2265
- const toolUseContext = options.toolUseContext;
2266
- if (toolUseContext && !toolUseContext.responseState) {
2267
- const conversationId = getConversationId(
2268
- toolUseContext.agentId,
2269
- toolUseContext.messageId
2270
- );
2271
- const previousResponseId = responseStateManager.getPreviousResponseId(conversationId);
2272
- toolUseContext.responseState = {
2273
- previousResponseId,
2274
- conversationId
2275
- };
2276
- }
2277
- debug.api("MODEL_RESOLVED", {
2278
- inputParam: options.model,
2279
- resolvedModelName: resolvedModel,
2280
- provider: modelProfile.provider,
2281
- isPointer: ["main", "task", "compact", "quick"].includes(options.model),
2282
- hasResponseState: !!toolUseContext?.responseState,
2283
- conversationId: toolUseContext?.responseState?.conversationId,
2284
- requestId: getCurrentRequest()?.id
2285
- });
2286
- const currentRequest = getCurrentRequest();
2287
- debug.api("LLM_REQUEST_START", {
2288
- messageCount: messages.length,
2289
- systemPromptLength: systemPrompt.join(" ").length,
2290
- toolCount: tools.length,
2291
- model: resolvedModel,
2292
- originalModelParam: options.model,
2293
- requestId: getCurrentRequest()?.id
2294
- });
2295
- markPhase("LLM_CALL");
2296
- try {
2297
- const queryFn = options.__testQueryLLMWithPromptCaching ?? queryLLMWithPromptCaching;
2298
- const cleanOptions = { ...options };
2299
- delete cleanOptions.__testModelManager;
2300
- delete cleanOptions.__testQueryLLMWithPromptCaching;
2301
- const runQuery = () => queryFn(
2302
- messages,
2303
- systemPrompt,
2304
- maxThinkingTokens,
2305
- tools,
2306
- signal,
2307
- {
2308
- ...cleanOptions,
2309
- model: resolvedModel,
2310
- modelProfile,
2311
- toolUseContext
2284
+ if (ch === "{") {
2285
+ tokens.push({ type: "brace", value: "{" });
2286
+ index++;
2287
+ continue;
2288
+ }
2289
+ if (ch === "}") {
2290
+ tokens.push({ type: "brace", value: "}" });
2291
+ index++;
2292
+ continue;
2293
+ }
2294
+ if (ch === "[") {
2295
+ tokens.push({ type: "paren", value: "[" });
2296
+ index++;
2297
+ continue;
2298
+ }
2299
+ if (ch === "]") {
2300
+ tokens.push({ type: "paren", value: "]" });
2301
+ index++;
2302
+ continue;
2303
+ }
2304
+ if (ch === ":") {
2305
+ tokens.push({ type: "separator", value: ":" });
2306
+ index++;
2307
+ continue;
2308
+ }
2309
+ if (ch === ",") {
2310
+ tokens.push({ type: "delimiter", value: "," });
2311
+ index++;
2312
+ continue;
2313
+ }
2314
+ if (ch === '"') {
2315
+ let value = "";
2316
+ let incomplete = false;
2317
+ ch = input[++index];
2318
+ while (ch !== '"') {
2319
+ if (index === input.length) {
2320
+ incomplete = true;
2321
+ break;
2322
+ }
2323
+ if (ch === "\\") {
2324
+ if (++index === input.length) {
2325
+ incomplete = true;
2326
+ break;
2327
+ }
2328
+ value += ch + input[index];
2329
+ ch = input[++index];
2330
+ } else {
2331
+ value += ch;
2332
+ ch = input[++index];
2333
+ }
2312
2334
  }
2313
- );
2314
- const result = options.__testQueryLLMWithPromptCaching ? await runQuery() : await withVCR(messages, runQuery);
2315
- debug.api("LLM_REQUEST_SUCCESS", {
2316
- costUSD: result.costUSD,
2317
- durationMs: result.durationMs,
2318
- responseLength: result.message.content?.length || 0,
2319
- requestId: getCurrentRequest()?.id
2320
- });
2321
- if (toolUseContext?.responseState?.conversationId && result.responseId) {
2322
- responseStateManager.setPreviousResponseId(
2323
- toolUseContext.responseState.conversationId,
2324
- result.responseId
2325
- );
2326
- debug.api("RESPONSE_STATE_UPDATED", {
2327
- conversationId: toolUseContext.responseState.conversationId,
2328
- responseId: result.responseId,
2329
- requestId: getCurrentRequest()?.id
2330
- });
2335
+ ch = input[++index];
2336
+ if (!incomplete) tokens.push({ type: "string", value });
2337
+ continue;
2331
2338
  }
2332
- return result;
2333
- } catch (error) {
2334
- logErrorWithDiagnosis(
2335
- error,
2336
- {
2337
- messageCount: messages.length,
2338
- systemPromptLength: systemPrompt.join(" ").length,
2339
- model: options.model,
2340
- toolCount: tools.length,
2341
- phase: "LLM_CALL"
2342
- },
2343
- currentRequest?.id
2344
- );
2345
- throw error;
2339
+ if (ch && /\s/.test(ch)) {
2340
+ index++;
2341
+ continue;
2342
+ }
2343
+ const digit = /[0-9]/;
2344
+ if (ch && digit.test(ch) || ch === "-" || ch === ".") {
2345
+ let value = "";
2346
+ if (ch === "-") {
2347
+ value += ch;
2348
+ ch = input[++index];
2349
+ }
2350
+ while (ch && digit.test(ch) || ch === ".") {
2351
+ value += ch;
2352
+ ch = input[++index];
2353
+ }
2354
+ tokens.push({ type: "number", value });
2355
+ continue;
2356
+ }
2357
+ const alpha = /[a-z]/i;
2358
+ if (ch && alpha.test(ch)) {
2359
+ let value = "";
2360
+ while (ch && alpha.test(ch)) {
2361
+ if (index === input.length) break;
2362
+ value += ch;
2363
+ ch = input[++index];
2364
+ }
2365
+ if (value === "true" || value === "false" || value === "null") {
2366
+ tokens.push({ type: "name", value });
2367
+ } else {
2368
+ index++;
2369
+ }
2370
+ continue;
2371
+ }
2372
+ index++;
2346
2373
  }
2374
+ return tokens;
2347
2375
  }
2348
- async function queryLLMWithPromptCaching(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
2349
- const config = getGlobalConfig();
2350
- const modelManager = getModelManager();
2351
- const toolUseContext = options.toolUseContext;
2352
- const modelProfile = options.modelProfile || modelManager.getModel("main");
2353
- let provider;
2354
- if (modelProfile) {
2355
- provider = modelProfile.provider || config.primaryProvider || "anthropic";
2356
- } else {
2357
- provider = config.primaryProvider || "anthropic";
2376
+ function trimTrailingIncompleteTokens(tokens) {
2377
+ if (tokens.length === 0) return tokens;
2378
+ const last = tokens[tokens.length - 1];
2379
+ if (last.type === "separator") {
2380
+ return trimTrailingIncompleteTokens(tokens.slice(0, -1));
2358
2381
  }
2359
- if (provider === "anthropic" || provider === "bigdream" || provider === "opendev" || provider === "minimax-coding") {
2360
- return queryAnthropicNative(
2361
- messages,
2362
- systemPrompt,
2363
- maxThinkingTokens,
2364
- tools,
2365
- signal,
2366
- { ...options, modelProfile, toolUseContext }
2367
- );
2382
+ if (last.type === "number") {
2383
+ const lastChar = last.value[last.value.length - 1];
2384
+ if (lastChar === "." || lastChar === "-") {
2385
+ return trimTrailingIncompleteTokens(tokens.slice(0, -1));
2386
+ }
2368
2387
  }
2369
- return queryOpenAI(messages, systemPrompt, maxThinkingTokens, tools, signal, {
2370
- ...options,
2371
- modelProfile,
2372
- toolUseContext
2373
- });
2388
+ if (last.type === "string" || last.type === "number") {
2389
+ const previous = tokens[tokens.length - 2];
2390
+ if (previous?.type === "delimiter") {
2391
+ return trimTrailingIncompleteTokens(tokens.slice(0, -1));
2392
+ }
2393
+ if (previous?.type === "brace" && previous.value === "{") {
2394
+ return trimTrailingIncompleteTokens(tokens.slice(0, -1));
2395
+ }
2396
+ }
2397
+ if (last.type === "delimiter") {
2398
+ return trimTrailingIncompleteTokens(tokens.slice(0, -1));
2399
+ }
2400
+ return tokens;
2374
2401
  }
2375
- async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
2376
- const config = getGlobalConfig();
2377
- const modelManager = getModelManager();
2378
- const toolUseContext = options?.toolUseContext;
2379
- const modelProfile = options?.modelProfile || modelManager.getModel("main");
2380
- let anthropic;
2381
- let model;
2382
- let provider;
2383
- debug.api("MODEL_CONFIG_ANTHROPIC", {
2384
- modelProfileFound: !!modelProfile,
2385
- modelProfileId: modelProfile?.modelName,
2386
- modelProfileName: modelProfile?.name,
2387
- modelProfileModelName: modelProfile?.modelName,
2388
- modelProfileProvider: modelProfile?.provider,
2402
+ function closeOpenBrackets(tokens) {
2403
+ const missingClosers = [];
2404
+ for (const token of tokens) {
2405
+ if (token.type === "brace") {
2406
+ if (token.value === "{") missingClosers.push("}");
2407
+ else missingClosers.splice(missingClosers.lastIndexOf("}"), 1);
2408
+ continue;
2409
+ }
2410
+ if (token.type === "paren") {
2411
+ if (token.value === "[") missingClosers.push("]");
2412
+ else missingClosers.splice(missingClosers.lastIndexOf("]"), 1);
2413
+ }
2414
+ }
2415
+ if (missingClosers.length > 0) {
2416
+ missingClosers.reverse();
2417
+ for (const closer of missingClosers) {
2418
+ if (closer === "}") tokens.push({ type: "brace", value: "}" });
2419
+ else tokens.push({ type: "paren", value: "]" });
2420
+ }
2421
+ }
2422
+ return tokens;
2423
+ }
2424
+ function tokensToJson(tokens) {
2425
+ let out = "";
2426
+ for (const token of tokens) {
2427
+ if (token.type === "string") out += `"${token.value}"`;
2428
+ else out += token.value;
2429
+ }
2430
+ return out;
2431
+ }
2432
+ function parseToolUsePartialJson(input) {
2433
+ const tokens = tokenizePartialJson(input);
2434
+ const trimmed = trimTrailingIncompleteTokens(tokens);
2435
+ const completed = closeOpenBrackets(trimmed);
2436
+ return JSON.parse(tokensToJson(completed));
2437
+ }
2438
+ function parseToolUsePartialJsonOrThrow(input) {
2439
+ try {
2440
+ return parseToolUsePartialJson(input);
2441
+ } catch (error) {
2442
+ throw new Error(
2443
+ `Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${String(error)}. JSON: ${input}`
2444
+ );
2445
+ }
2446
+ }
2447
+
2448
+ // packages/core/src/ai/llm/anthropic/streaming.ts
2449
+ function asRecord2(value) {
2450
+ if (!value || typeof value !== "object") return null;
2451
+ if (Array.isArray(value)) return null;
2452
+ return value;
2453
+ }
2454
+ async function createAnthropicStreamingMessage(anthropic, params, signal) {
2455
+ const stream = await anthropic.beta.messages.create(
2456
+ {
2457
+ ...params,
2458
+ stream: true
2459
+ },
2460
+ {
2461
+ signal
2462
+ // ← CRITICAL: Connect the AbortSignal to API call
2463
+ }
2464
+ );
2465
+ let finalResponse = null;
2466
+ let messageStartEvent = null;
2467
+ const contentBlocks = [];
2468
+ const inputJSONBuffers = /* @__PURE__ */ new Map();
2469
+ let usage = null;
2470
+ let stopReason = null;
2471
+ let stopSequence = null;
2472
+ let hasMarkedStreaming = false;
2473
+ for await (const event of stream) {
2474
+ if (signal.aborted) {
2475
+ debug.flow("STREAM_ABORTED", {
2476
+ eventType: event.type,
2477
+ timestamp: Date.now()
2478
+ });
2479
+ throw new Error("Request was cancelled");
2480
+ }
2481
+ switch (event.type) {
2482
+ case "message_start":
2483
+ messageStartEvent = event;
2484
+ finalResponse = {
2485
+ ...event.message,
2486
+ content: []
2487
+ // Will be populated from content blocks
2488
+ };
2489
+ break;
2490
+ case "content_block_start":
2491
+ contentBlocks[event.index] = { ...event.content_block };
2492
+ {
2493
+ const contentBlock = asRecord2(event.content_block);
2494
+ const blockType = contentBlock?.type;
2495
+ if (blockType === "tool_use" || blockType === "server_tool_use" || blockType === "mcp_tool_use") {
2496
+ setRequestStatus({
2497
+ kind: "tool",
2498
+ detail: typeof contentBlock?.name === "string" ? contentBlock.name : void 0
2499
+ });
2500
+ inputJSONBuffers.set(event.index, "");
2501
+ }
2502
+ }
2503
+ break;
2504
+ case "content_block_delta":
2505
+ const blockIndex = event.index;
2506
+ if (!contentBlocks[blockIndex]) {
2507
+ contentBlocks[blockIndex] = {
2508
+ type: event.delta.type === "text_delta" ? "text" : "tool_use",
2509
+ text: event.delta.type === "text_delta" ? "" : void 0
2510
+ };
2511
+ if (event.delta.type === "input_json_delta") {
2512
+ inputJSONBuffers.set(blockIndex, "");
2513
+ }
2514
+ }
2515
+ if (event.delta.type === "text_delta") {
2516
+ if (!hasMarkedStreaming) {
2517
+ setRequestStatus({ kind: "streaming" });
2518
+ hasMarkedStreaming = true;
2519
+ }
2520
+ contentBlocks[blockIndex].text += event.delta.text;
2521
+ } else if (event.delta.type === "input_json_delta") {
2522
+ const currentBuffer = inputJSONBuffers.get(blockIndex) || "";
2523
+ const nextBuffer = currentBuffer + event.delta.partial_json;
2524
+ inputJSONBuffers.set(blockIndex, nextBuffer);
2525
+ const trimmed = nextBuffer.trim();
2526
+ if (trimmed.length === 0) {
2527
+ contentBlocks[blockIndex].input = {};
2528
+ break;
2529
+ }
2530
+ contentBlocks[blockIndex].input = parseToolUsePartialJsonOrThrow(nextBuffer) ?? {};
2531
+ }
2532
+ break;
2533
+ case "message_delta":
2534
+ if (event.delta.stop_reason) stopReason = event.delta.stop_reason;
2535
+ if (event.delta.stop_sequence) stopSequence = event.delta.stop_sequence;
2536
+ if (event.usage) usage = { ...usage, ...event.usage };
2537
+ break;
2538
+ case "content_block_stop":
2539
+ const stopIndex = event.index;
2540
+ const block = contentBlocks[stopIndex];
2541
+ if ((block?.type === "tool_use" || block?.type === "server_tool_use" || block?.type === "mcp_tool_use") && inputJSONBuffers.has(stopIndex)) {
2542
+ const jsonStr = inputJSONBuffers.get(stopIndex) ?? "";
2543
+ if (block.input === void 0) {
2544
+ const trimmed = jsonStr.trim();
2545
+ if (trimmed.length === 0) {
2546
+ block.input = {};
2547
+ } else {
2548
+ block.input = parseToolUsePartialJsonOrThrow(jsonStr) ?? {};
2549
+ }
2550
+ }
2551
+ inputJSONBuffers.delete(stopIndex);
2552
+ }
2553
+ break;
2554
+ case "message_stop":
2555
+ inputJSONBuffers.clear();
2556
+ break;
2557
+ }
2558
+ if (event.type === "message_stop") {
2559
+ break;
2560
+ }
2561
+ }
2562
+ if (!finalResponse || !messageStartEvent) {
2563
+ throw new Error("Stream ended without proper message structure");
2564
+ }
2565
+ finalResponse = {
2566
+ ...messageStartEvent.message,
2567
+ content: contentBlocks.filter(Boolean),
2568
+ stop_reason: stopReason,
2569
+ stop_sequence: stopSequence,
2570
+ usage: {
2571
+ ...messageStartEvent.message.usage,
2572
+ ...usage
2573
+ }
2574
+ };
2575
+ return finalResponse;
2576
+ }
2577
+
2578
+ // packages/core/src/ai/llm/anthropic/cost.ts
2579
+ function getModelInputTokenCostUSD(model) {
2580
+ for (const providerModels of Object.values(models_default)) {
2581
+ const modelInfo = providerModels.find((m) => m.model === model);
2582
+ if (modelInfo) {
2583
+ return modelInfo.input_cost_per_token || 0;
2584
+ }
2585
+ }
2586
+ return 3e-6;
2587
+ }
2588
+ function getModelOutputTokenCostUSD(model) {
2589
+ for (const providerModels of Object.values(models_default)) {
2590
+ const modelInfo = providerModels.find((m) => m.model === model);
2591
+ if (modelInfo) {
2592
+ return modelInfo.output_cost_per_token || 0;
2593
+ }
2594
+ }
2595
+ return 15e-6;
2596
+ }
2597
+
2598
+ // packages/core/src/ai/llm/anthropic/native.ts
2599
+ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
2600
+ const config = getGlobalConfig();
2601
+ const modelManager = getModelManager();
2602
+ const toolUseContext = options?.toolUseContext;
2603
+ const modelProfile = options?.modelProfile || modelManager.getModel("main");
2604
+ let anthropic;
2605
+ let model;
2606
+ let provider;
2607
+ debug.api("MODEL_CONFIG_ANTHROPIC", {
2608
+ modelProfileFound: !!modelProfile,
2609
+ modelProfileId: modelProfile?.modelName,
2610
+ modelProfileName: modelProfile?.name,
2611
+ modelProfileModelName: modelProfile?.modelName,
2612
+ modelProfileProvider: modelProfile?.provider,
2389
2613
  modelProfileBaseURL: modelProfile?.baseURL,
2390
2614
  modelProfileApiKeyExists: !!modelProfile?.apiKey,
2391
2615
  optionsModel: options?.model,
@@ -2408,7 +2632,7 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2408
2632
  if (modelProfile.baseURL) {
2409
2633
  clientConfig.baseURL = modelProfile.baseURL;
2410
2634
  }
2411
- anthropic = new Anthropic(clientConfig);
2635
+ anthropic = new Anthropic2(clientConfig);
2412
2636
  } else {
2413
2637
  anthropic = getAnthropicClient(model);
2414
2638
  }
@@ -2439,7 +2663,7 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2439
2663
  async (tool) => ({
2440
2664
  name: tool.name,
2441
2665
  description: getToolDescription(tool),
2442
- input_schema: "inputJSONSchema" in tool && tool.inputJSONSchema ? tool.inputJSONSchema : zodToJsonSchema4(tool.inputSchema)
2666
+ input_schema: "inputJSONSchema" in tool && tool.inputJSONSchema ? tool.inputJSONSchema : zodToJsonSchema5(tool.inputSchema)
2443
2667
  })
2444
2668
  )
2445
2669
  );
@@ -2450,6 +2674,7 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2450
2674
  basePrompt: systemPrompt.join("\n"),
2451
2675
  kodeContext: generateKodeContext() || "",
2452
2676
  reminders: [],
2677
+ // 这里可以从 generateSystemReminders 获取
2453
2678
  finalPrompt: systemPrompt.join("\n")
2454
2679
  });
2455
2680
  let start = Date.now();
@@ -2462,7 +2687,7 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2462
2687
  start = Date.now();
2463
2688
  const params = {
2464
2689
  model,
2465
- max_tokens: options?.maxTokens ?? getMaxTokensFromProfile(modelProfile),
2690
+ max_tokens: options?.maxTokens ?? getMaxTokensFromProfile2(modelProfile),
2466
2691
  messages: processedMessages,
2467
2692
  system: processedSystem,
2468
2693
  tools: toolSchemas.length > 0 ? toolSchemas : void 0,
@@ -2471,148 +2696,37 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2471
2696
  ...options?.stopSequences && options.stopSequences.length > 0 ? { stop_sequences: options.stopSequences } : {}
2472
2697
  };
2473
2698
  if (maxThinkingTokens > 0) {
2474
- ;
2475
2699
  params.extra_headers = {
2476
2700
  "anthropic-beta": "max-tokens-3-5-sonnet-2024-07-15"
2477
2701
  };
2478
- params.thinking = { max_tokens: maxThinkingTokens };
2702
+ params.thinking = {
2703
+ type: "enabled",
2704
+ budget_tokens: maxThinkingTokens
2705
+ };
2479
2706
  }
2480
- debug.api("ANTHROPIC_API_CALL_START_STREAMING", {
2481
- endpoint: modelProfile?.baseURL || "DEFAULT_ANTHROPIC",
2482
- model,
2483
- provider,
2484
- apiKeyConfigured: !!modelProfile?.apiKey,
2485
- apiKeyPrefix: modelProfile?.apiKey ? modelProfile.apiKey.substring(0, 8) : null,
2486
- maxTokens: params.max_tokens,
2487
- temperature: options?.temperature ?? MAIN_QUERY_TEMPERATURE,
2488
- params,
2489
- messageCount: params.messages?.length || 0,
2490
- streamMode: true,
2491
- toolsCount: toolSchemas.length,
2492
- thinkingTokens: maxThinkingTokens,
2493
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2494
- modelProfileId: modelProfile?.modelName,
2495
- modelProfileName: modelProfile?.name
2496
- });
2497
2707
  if (config.stream) {
2498
- const stream = await anthropic.beta.messages.create(
2499
- {
2500
- ...params,
2501
- stream: true
2502
- },
2503
- {
2504
- signal
2505
- }
2708
+ debug.api("ANTHROPIC_API_CALL_START_STREAMING", {
2709
+ endpoint: modelProfile?.baseURL || "DEFAULT_ANTHROPIC",
2710
+ model,
2711
+ provider,
2712
+ apiKeyConfigured: !!modelProfile?.apiKey,
2713
+ apiKeyPrefix: modelProfile?.apiKey ? modelProfile.apiKey.substring(0, 8) : null,
2714
+ maxTokens: params.max_tokens,
2715
+ temperature: options?.temperature ?? MAIN_QUERY_TEMPERATURE,
2716
+ params,
2717
+ messageCount: params.messages?.length || 0,
2718
+ streamMode: true,
2719
+ toolsCount: toolSchemas.length,
2720
+ thinkingTokens: maxThinkingTokens,
2721
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2722
+ modelProfileId: modelProfile?.modelName,
2723
+ modelProfileName: modelProfile?.name
2724
+ });
2725
+ return await createAnthropicStreamingMessage(
2726
+ anthropic,
2727
+ params,
2728
+ signal
2506
2729
  );
2507
- let finalResponse = null;
2508
- let messageStartEvent = null;
2509
- const contentBlocks = [];
2510
- const inputJSONBuffers = /* @__PURE__ */ new Map();
2511
- let usage = null;
2512
- let stopReason = null;
2513
- let stopSequence = null;
2514
- let hasMarkedStreaming = false;
2515
- for await (const event of stream) {
2516
- if (signal.aborted) {
2517
- debug.flow("STREAM_ABORTED", {
2518
- eventType: event.type,
2519
- timestamp: Date.now()
2520
- });
2521
- throw new Error("Request was cancelled");
2522
- }
2523
- switch (event.type) {
2524
- case "message_start":
2525
- messageStartEvent = event;
2526
- finalResponse = {
2527
- ...event.message,
2528
- content: []
2529
- };
2530
- break;
2531
- case "content_block_start":
2532
- contentBlocks[event.index] = { ...event.content_block };
2533
- const contentBlockType = event.content_block.type;
2534
- if (contentBlockType === "tool_use" || contentBlockType === "server_tool_use" || contentBlockType === "mcp_tool_use") {
2535
- setRequestStatus({
2536
- kind: "tool",
2537
- detail: event.content_block.name
2538
- });
2539
- inputJSONBuffers.set(event.index, "");
2540
- }
2541
- break;
2542
- case "content_block_delta":
2543
- const blockIndex = event.index;
2544
- if (!contentBlocks[blockIndex]) {
2545
- contentBlocks[blockIndex] = {
2546
- type: event.delta.type === "text_delta" ? "text" : "tool_use",
2547
- text: event.delta.type === "text_delta" ? "" : void 0
2548
- };
2549
- if (event.delta.type === "input_json_delta") {
2550
- inputJSONBuffers.set(blockIndex, "");
2551
- }
2552
- }
2553
- if (event.delta.type === "text_delta") {
2554
- if (!hasMarkedStreaming) {
2555
- setRequestStatus({ kind: "streaming" });
2556
- hasMarkedStreaming = true;
2557
- }
2558
- contentBlocks[blockIndex].text += event.delta.text;
2559
- } else if (event.delta.type === "input_json_delta") {
2560
- const currentBuffer = inputJSONBuffers.get(blockIndex) || "";
2561
- const nextBuffer = currentBuffer + event.delta.partial_json;
2562
- inputJSONBuffers.set(blockIndex, nextBuffer);
2563
- const trimmed = nextBuffer.trim();
2564
- if (trimmed.length === 0) {
2565
- contentBlocks[blockIndex].input = {};
2566
- break;
2567
- }
2568
- contentBlocks[blockIndex].input = parseToolUsePartialJsonOrThrow(nextBuffer) ?? {};
2569
- }
2570
- break;
2571
- case "message_delta":
2572
- if (event.delta.stop_reason)
2573
- stopReason = event.delta.stop_reason;
2574
- if (event.delta.stop_sequence)
2575
- stopSequence = event.delta.stop_sequence;
2576
- if (event.usage) usage = { ...usage, ...event.usage };
2577
- break;
2578
- case "content_block_stop":
2579
- const stopIndex = event.index;
2580
- const block = contentBlocks[stopIndex];
2581
- if ((block?.type === "tool_use" || block?.type === "server_tool_use" || block?.type === "mcp_tool_use") && inputJSONBuffers.has(stopIndex)) {
2582
- const jsonStr = inputJSONBuffers.get(stopIndex) ?? "";
2583
- if (block.input === void 0) {
2584
- const trimmed = jsonStr.trim();
2585
- if (trimmed.length === 0) {
2586
- block.input = {};
2587
- } else {
2588
- block.input = parseToolUsePartialJsonOrThrow(jsonStr) ?? {};
2589
- }
2590
- }
2591
- inputJSONBuffers.delete(stopIndex);
2592
- }
2593
- break;
2594
- case "message_stop":
2595
- inputJSONBuffers.clear();
2596
- break;
2597
- }
2598
- if (event.type === "message_stop") {
2599
- break;
2600
- }
2601
- }
2602
- if (!finalResponse || !messageStartEvent) {
2603
- throw new Error("Stream ended without proper message structure");
2604
- }
2605
- finalResponse = {
2606
- ...messageStartEvent.message,
2607
- content: contentBlocks.filter(Boolean),
2608
- stop_reason: stopReason,
2609
- stop_sequence: stopSequence,
2610
- usage: {
2611
- ...messageStartEvent.message.usage,
2612
- ...usage
2613
- }
2614
- };
2615
- return finalResponse;
2616
2730
  } else {
2617
2731
  debug.api("ANTHROPIC_API_CALL_START_NON_STREAMING", {
2618
2732
  endpoint: modelProfile?.baseURL || "DEFAULT_ANTHROPIC",
@@ -2632,6 +2746,7 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2632
2746
  });
2633
2747
  return await anthropic.beta.messages.create(params, {
2634
2748
  signal
2749
+ // ← CRITICAL: Connect the AbortSignal to API call
2635
2750
  });
2636
2751
  }
2637
2752
  },
@@ -2640,7 +2755,7 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2640
2755
  debug.api("ANTHROPIC_API_CALL_SUCCESS", {
2641
2756
  content: response.content
2642
2757
  });
2643
- const ttftMs = start - Date.now();
2758
+ const ttftMs = Date.now() - start;
2644
2759
  const durationMs = Date.now() - startIncludingRetries;
2645
2760
  const content = response.content.map((block) => {
2646
2761
  if (block.type === "text") {
@@ -2670,9 +2785,10 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2670
2785
  usage: response.usage
2671
2786
  },
2672
2787
  type: "assistant",
2673
- uuid: nanoid(),
2788
+ uuid: nanoid3(),
2674
2789
  durationMs,
2675
2790
  costUSD: 0
2791
+ // Will be calculated below
2676
2792
  };
2677
2793
  const systemMessages = system.map((block) => ({
2678
2794
  role: "system",
@@ -2704,374 +2820,466 @@ async function queryAnthropicNative(messages, systemPrompt, maxThinkingTokens, t
2704
2820
  return getAssistantMessageFromError(error);
2705
2821
  }
2706
2822
  }
2707
- function getAssistantMessageFromError(error) {
2708
- if (error instanceof Error && error.message.includes("prompt is too long")) {
2709
- return createAssistantAPIErrorMessage(PROMPT_TOO_LONG_ERROR_MESSAGE);
2710
- }
2711
- if (error instanceof Error && error.message.includes("Your credit balance is too low")) {
2712
- return createAssistantAPIErrorMessage(CREDIT_BALANCE_TOO_LOW_ERROR_MESSAGE);
2823
+
2824
+ // packages/core/src/services/vcr.ts
2825
+ import { createHash } from "crypto";
2826
+ import { mkdirSync, readFileSync, writeFileSync } from "fs";
2827
+ import { dirname } from "path";
2828
+ import { existsSync } from "fs";
2829
+ import * as path from "path";
2830
+ import { mapValues } from "lodash-es";
2831
+ async function withVCR(messages, f) {
2832
+ if (process.env.NODE_ENV !== "test") {
2833
+ return await f();
2713
2834
  }
2714
- if (error instanceof Error && error.message.toLowerCase().includes("x-api-key")) {
2715
- return createAssistantAPIErrorMessage(INVALID_API_KEY_ERROR_MESSAGE);
2835
+ const dehydratedInput = mapMessages(
2836
+ messages.map((_) => _.message.content),
2837
+ dehydrateValue
2838
+ );
2839
+ const filename = `./fixtures/${dehydratedInput.map((_) => createHash("sha1").update(JSON.stringify(_)).digest("hex").slice(0, 6)).join("-")}.json`;
2840
+ if (existsSync(filename)) {
2841
+ const cached = JSON.parse(readFileSync(filename, "utf-8"));
2842
+ return mapAssistantMessage(cached.output, hydrateValue);
2716
2843
  }
2717
- if (error instanceof Error) {
2718
- if (process.env.NODE_ENV === "development") {
2719
- debug.error("ANTHROPIC_API_ERROR", {
2720
- message: error.message,
2721
- stack: error.stack
2722
- });
2723
- }
2724
- return createAssistantAPIErrorMessage(
2725
- `${API_ERROR_MESSAGE_PREFIX}: ${error.message}`
2844
+ if (env.isCI) {
2845
+ process.stderr.write(
2846
+ `Anthropic API fixture missing. Re-run bun test locally, then commit the result. ${JSON.stringify({ input: dehydratedInput }, null, 2)}
2847
+ `
2726
2848
  );
2727
2849
  }
2728
- return createAssistantAPIErrorMessage(API_ERROR_MESSAGE_PREFIX);
2729
- }
2730
- function addCacheBreakpoints(messages) {
2731
- return messages.map((msg, index) => {
2732
- return msg.type === "user" ? userMessageToMessageParam(msg, index > messages.length - 3) : assistantMessageToMessageParam(msg, index > messages.length - 3);
2733
- });
2734
- }
2735
- async function queryOpenAI(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
2736
- const config = getGlobalConfig();
2737
- const modelManager = getModelManager();
2738
- const toolUseContext = options?.toolUseContext;
2739
- const modelProfile = options?.modelProfile || modelManager.getModel("main");
2740
- let model;
2741
- const currentRequest = getCurrentRequest();
2742
- debug.api("MODEL_CONFIG_OPENAI", {
2743
- modelProfileFound: !!modelProfile,
2744
- modelProfileId: modelProfile?.modelName,
2745
- modelProfileName: modelProfile?.name,
2746
- modelProfileModelName: modelProfile?.modelName,
2747
- modelProfileProvider: modelProfile?.provider,
2748
- modelProfileBaseURL: modelProfile?.baseURL,
2749
- modelProfileApiKeyExists: !!modelProfile?.apiKey,
2750
- optionsModel: options?.model,
2751
- requestId: getCurrentRequest()?.id
2752
- });
2753
- if (modelProfile) {
2754
- model = modelProfile.modelName;
2755
- } else {
2756
- model = options?.model || modelProfile?.modelName || "";
2850
+ const result = await f();
2851
+ if (env.isCI) {
2852
+ return result;
2757
2853
  }
2758
- if (options?.prependCLISysprompt) {
2759
- const [firstSyspromptBlock] = splitSysPromptPrefix(systemPrompt);
2760
- systemPrompt = [getCLISyspromptPrefix() + systemPrompt];
2854
+ if (!existsSync(dirname(filename))) {
2855
+ mkdirSync(dirname(filename), { recursive: true });
2761
2856
  }
2762
- const system = splitSysPromptPrefix(systemPrompt).map(
2763
- (_) => ({
2764
- ...PROMPT_CACHING_ENABLED ? { cache_control: { type: "ephemeral" } } : {},
2765
- text: _,
2766
- type: "text"
2767
- })
2768
- );
2769
- const toolSchemas = await Promise.all(
2770
- tools.map(
2771
- async (_) => ({
2772
- type: "function",
2773
- function: {
2774
- name: _.name,
2775
- description: await _.prompt({
2776
- safeMode: options?.safeMode
2777
- }),
2778
- parameters: "inputJSONSchema" in _ && _.inputJSONSchema ? _.inputJSONSchema : zodToJsonSchema4(_.inputSchema)
2779
- }
2780
- })
2857
+ writeFileSync(
2858
+ filename,
2859
+ JSON.stringify(
2860
+ {
2861
+ input: dehydratedInput,
2862
+ output: mapAssistantMessage(result, dehydrateValue)
2863
+ },
2864
+ null,
2865
+ 2
2781
2866
  )
2782
2867
  );
2783
- const openaiSystem = system.map(
2784
- (s) => ({
2785
- role: "system",
2786
- content: s.text
2787
- })
2788
- );
2789
- const openaiMessages = convertAnthropicMessagesToOpenAIMessages2(messages);
2790
- logSystemPromptConstruction({
2791
- basePrompt: systemPrompt.join("\n"),
2792
- kodeContext: generateKodeContext() || "",
2793
- reminders: [],
2794
- finalPrompt: systemPrompt.join("\n")
2795
- });
2796
- let start = Date.now();
2797
- let adapterContext = null;
2798
- if (modelProfile && modelProfile.modelName) {
2799
- debug.api("CHECKING_ADAPTER_SYSTEM", {
2800
- modelProfileName: modelProfile.modelName,
2801
- modelName: modelProfile.modelName,
2802
- provider: modelProfile.provider,
2803
- requestId: getCurrentRequest()?.id
2804
- });
2805
- const USE_NEW_ADAPTER_SYSTEM = process.env.USE_NEW_ADAPTERS !== "false";
2806
- if (USE_NEW_ADAPTER_SYSTEM) {
2807
- const shouldUseResponses = ModelAdapterFactory.shouldUseResponsesAPI(modelProfile);
2808
- if (shouldUseResponses) {
2809
- const adapter = ModelAdapterFactory.createAdapter(modelProfile);
2810
- const reasoningEffort = await getReasoningEffort(modelProfile, messages);
2811
- let verbosity = "medium";
2812
- const modelNameLower = modelProfile.modelName.toLowerCase();
2813
- if (modelNameLower.includes("high")) {
2814
- verbosity = "high";
2815
- } else if (modelNameLower.includes("low")) {
2816
- verbosity = "low";
2817
- }
2818
- const unifiedParams = {
2819
- messages: openaiMessages,
2820
- systemPrompt: openaiSystem.map((s) => s.content),
2821
- tools,
2822
- maxTokens: options?.maxTokens ?? getMaxTokensFromProfile(modelProfile),
2823
- stream: config.stream,
2824
- reasoningEffort,
2825
- temperature: options?.temperature ?? (isGPT5Model(model) ? 1 : MAIN_QUERY_TEMPERATURE),
2826
- previousResponseId: toolUseContext?.responseState?.previousResponseId,
2827
- verbosity,
2828
- ...options?.stopSequences && options.stopSequences.length > 0 ? { stopSequences: options.stopSequences } : {}
2829
- };
2830
- adapterContext = {
2831
- adapter,
2832
- request: adapter.createRequest(unifiedParams),
2833
- shouldUseResponses: true
2834
- };
2835
- }
2868
+ return result;
2869
+ }
2870
+ function mapMessages(messages, f) {
2871
+ return messages.map((_) => {
2872
+ if (typeof _ === "string") {
2873
+ return f(_);
2836
2874
  }
2837
- }
2838
- let queryResult;
2839
- let startIncludingRetries = Date.now();
2840
- try {
2841
- queryResult = await withRetry(
2842
- async () => {
2843
- start = Date.now();
2844
- if (adapterContext) {
2845
- if (adapterContext.shouldUseResponses) {
2846
- const { callGPT5ResponsesAPI } = await import("./openai-RRCWW33N.js");
2847
- const response = await callGPT5ResponsesAPI(
2848
- modelProfile,
2849
- adapterContext.request,
2850
- signal
2851
- );
2852
- const unifiedResponse = await adapterContext.adapter.parseResponse(response);
2853
- const assistantMessage2 = buildAssistantMessageFromUnifiedResponse(
2854
- unifiedResponse,
2855
- start
2856
- );
2857
- assistantMessage2.message.usage = normalizeUsage(
2858
- assistantMessage2.message.usage
2859
- );
2875
+ return _.map((_2) => {
2876
+ switch (_2.type) {
2877
+ case "tool_result":
2878
+ if (typeof _2.content === "string") {
2879
+ return { ..._2, content: f(_2.content) };
2880
+ }
2881
+ if (Array.isArray(_2.content)) {
2860
2882
  return {
2861
- assistantMessage: assistantMessage2,
2862
- rawResponse: unifiedResponse,
2863
- apiFormat: "openai"
2883
+ ..._2,
2884
+ content: _2.content.map((_3) => {
2885
+ switch (_3.type) {
2886
+ case "text":
2887
+ return { ..._3, text: f(_3.text) };
2888
+ case "image":
2889
+ return _3;
2890
+ }
2891
+ })
2864
2892
  };
2865
2893
  }
2866
- const s2 = await getCompletionWithProfile(
2867
- modelProfile,
2868
- adapterContext.request,
2869
- 0,
2870
- 10,
2871
- signal
2872
- );
2873
- let finalResponse2;
2874
- if (config.stream) {
2875
- finalResponse2 = await handleMessageStream(
2876
- s2,
2877
- signal
2878
- );
2879
- } else {
2880
- finalResponse2 = s2;
2881
- }
2882
- const message2 = convertOpenAIResponseToAnthropic(finalResponse2, tools);
2883
- const assistantMsg2 = {
2884
- type: "assistant",
2885
- message: message2,
2886
- costUSD: 0,
2887
- durationMs: Date.now() - start,
2888
- uuid: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
2889
- };
2894
+ return _2;
2895
+ case "text":
2896
+ return { ..._2, text: f(_2.text) };
2897
+ case "tool_use":
2890
2898
  return {
2891
- assistantMessage: assistantMsg2,
2892
- rawResponse: finalResponse2,
2893
- apiFormat: "openai"
2894
- };
2895
- }
2896
- const maxTokens = options?.maxTokens ?? getMaxTokensFromProfile(modelProfile);
2897
- const isGPT5 = isGPT5Model(model);
2898
- const opts = {
2899
- model,
2900
- ...isGPT5 ? { max_completion_tokens: maxTokens } : { max_tokens: maxTokens },
2901
- messages: [...openaiSystem, ...openaiMessages],
2902
- temperature: options?.temperature ?? (isGPT5 ? 1 : MAIN_QUERY_TEMPERATURE)
2903
- };
2904
- if (options?.stopSequences && options.stopSequences.length > 0) {
2905
- ;
2906
- opts.stop = options.stopSequences;
2907
- }
2908
- if (config.stream) {
2909
- ;
2910
- opts.stream = true;
2911
- opts.stream_options = {
2912
- include_usage: true
2899
+ ..._2,
2900
+ input: mapValues(_2.input, f)
2913
2901
  };
2902
+ case "image":
2903
+ return _2;
2904
+ }
2905
+ });
2906
+ });
2907
+ }
2908
+ function mapAssistantMessage(message, f) {
2909
+ return {
2910
+ durationMs: "DURATION",
2911
+ costUSD: "COST",
2912
+ uuid: "UUID",
2913
+ message: {
2914
+ ...message.message,
2915
+ content: message.message.content.map((_) => {
2916
+ switch (_.type) {
2917
+ case "text":
2918
+ return {
2919
+ ..._,
2920
+ text: f(_.text),
2921
+ citations: _.citations || []
2922
+ };
2923
+ // Ensure citations
2924
+ case "tool_use":
2925
+ return {
2926
+ ..._,
2927
+ input: mapValues(_.input, f)
2928
+ };
2929
+ default:
2930
+ return _;
2914
2931
  }
2915
- if (toolSchemas.length > 0) {
2916
- opts.tools = toolSchemas;
2917
- opts.tool_choice = "auto";
2918
- }
2919
- const reasoningEffort = await getReasoningEffort(modelProfile, messages);
2920
- if (reasoningEffort) {
2921
- opts.reasoning_effort = reasoningEffort;
2922
- }
2923
- const completionFunction = isGPT5Model(modelProfile?.modelName || "") ? getGPT5CompletionWithProfile : getCompletionWithProfile;
2924
- const s = await completionFunction(modelProfile, opts, 0, 10, signal);
2925
- let finalResponse;
2926
- if (opts.stream) {
2927
- finalResponse = await handleMessageStream(
2928
- s,
2929
- signal
2930
- );
2931
- } else {
2932
- finalResponse = s;
2933
- }
2934
- const message = convertOpenAIResponseToAnthropic(finalResponse, tools);
2935
- const assistantMsg = {
2936
- type: "assistant",
2937
- message,
2938
- costUSD: 0,
2939
- durationMs: Date.now() - start,
2940
- uuid: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
2941
- };
2942
- return {
2943
- assistantMessage: assistantMsg,
2944
- rawResponse: finalResponse,
2945
- apiFormat: "openai"
2946
- };
2932
+ }).filter(Boolean)
2933
+ },
2934
+ type: "assistant"
2935
+ };
2936
+ }
2937
+ function dehydrateValue(s) {
2938
+ if (typeof s !== "string") {
2939
+ return s;
2940
+ }
2941
+ const s1 = s.replace(/num_files="\d+"/g, 'num_files="[NUM]"').replace(/duration_ms="\d+"/g, 'duration_ms="[DURATION]"').replace(/cost_usd="\d+"/g, 'cost_usd="[COST]"').replace(/\//g, path.sep).replaceAll(getCwd(), "[CWD]");
2942
+ if (s1.includes("Files modified by user:")) {
2943
+ return "Files modified by user: [FILES]";
2944
+ }
2945
+ return s1;
2946
+ }
2947
+ function hydrateValue(s) {
2948
+ if (typeof s !== "string") {
2949
+ return s;
2950
+ }
2951
+ return s.replaceAll("[NUM]", "1").replaceAll("[DURATION]", "100").replaceAll("[CWD]", getCwd());
2952
+ }
2953
+
2954
+ // packages/core/src/services/responseStateManager.ts
2955
+ var ResponseStateManager = class {
2956
+ conversationStates = /* @__PURE__ */ new Map();
2957
+ // Cache cleanup after 1 hour of inactivity
2958
+ CLEANUP_INTERVAL = 60 * 60 * 1e3;
2959
+ constructor() {
2960
+ setInterval(() => {
2961
+ this.cleanup();
2962
+ }, this.CLEANUP_INTERVAL);
2963
+ }
2964
+ /**
2965
+ * Set the previous response ID for a conversation
2966
+ */
2967
+ setPreviousResponseId(conversationId, responseId) {
2968
+ this.conversationStates.set(conversationId, {
2969
+ previousResponseId: responseId,
2970
+ lastUpdate: Date.now()
2971
+ });
2972
+ }
2973
+ /**
2974
+ * Get the previous response ID for a conversation
2975
+ */
2976
+ getPreviousResponseId(conversationId) {
2977
+ const state = this.conversationStates.get(conversationId);
2978
+ if (state) {
2979
+ state.lastUpdate = Date.now();
2980
+ return state.previousResponseId;
2981
+ }
2982
+ return void 0;
2983
+ }
2984
+ /**
2985
+ * Clear state for a conversation
2986
+ */
2987
+ clearConversation(conversationId) {
2988
+ this.conversationStates.delete(conversationId);
2989
+ }
2990
+ /**
2991
+ * Clear all conversation states
2992
+ */
2993
+ clearAll() {
2994
+ this.conversationStates.clear();
2995
+ }
2996
+ /**
2997
+ * Clean up stale conversations
2998
+ */
2999
+ cleanup() {
3000
+ const now = Date.now();
3001
+ for (const [conversationId, state] of this.conversationStates.entries()) {
3002
+ if (now - state.lastUpdate > this.CLEANUP_INTERVAL) {
3003
+ this.conversationStates.delete(conversationId);
3004
+ }
3005
+ }
3006
+ }
3007
+ /**
3008
+ * Get current state size (for debugging/monitoring)
3009
+ */
3010
+ getStateSize() {
3011
+ return this.conversationStates.size;
3012
+ }
3013
+ };
3014
+ var responseStateManager = new ResponseStateManager();
3015
+ function getConversationId(agentId, messageId) {
3016
+ return agentId || messageId || `conv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
3017
+ }
3018
+
3019
+ // packages/core/src/ai/llm/apiKey.ts
3020
+ import "@anthropic-ai/sdk/shims/node";
3021
+ import Anthropic3 from "@anthropic-ai/sdk";
3022
+ async function fetchAnthropicModels(baseURL, apiKey) {
3023
+ try {
3024
+ const modelsURL = baseURL ? `${baseURL.replace(/\/+$/, "")}/v1/models` : "https://api.anthropic.com/v1/models";
3025
+ const response = await fetch(modelsURL, {
3026
+ method: "GET",
3027
+ headers: {
3028
+ "x-api-key": apiKey,
3029
+ "anthropic-version": "2023-06-01",
3030
+ "User-Agent": USER_AGENT
3031
+ }
3032
+ });
3033
+ if (!response.ok) {
3034
+ if (response.status === 401) {
3035
+ throw new Error(
3036
+ "Invalid API key. Please check your Anthropic API key and try again."
3037
+ );
3038
+ } else if (response.status === 403) {
3039
+ throw new Error(
3040
+ "API key does not have permission to access models. Please check your API key permissions."
3041
+ );
3042
+ } else if (response.status === 429) {
3043
+ throw new Error(
3044
+ "Too many requests. Please wait a moment and try again."
3045
+ );
3046
+ } else if (response.status >= 500) {
3047
+ throw new Error(
3048
+ "Anthropic service is temporarily unavailable. Please try again later."
3049
+ );
3050
+ } else {
3051
+ throw new Error(
3052
+ `Unable to connect to Anthropic API (${response.status}). Please check your internet connection and API key.`
3053
+ );
3054
+ }
3055
+ }
3056
+ const data = await response.json();
3057
+ return data.data || [];
3058
+ } catch (error) {
3059
+ if (error instanceof Error && error.message.includes("API key") || error instanceof Error && error.message.includes("Anthropic")) {
3060
+ throw error;
3061
+ }
3062
+ logError(error);
3063
+ debug.warn("ANTHROPIC_MODELS_FETCH_FAILED", {
3064
+ error: error instanceof Error ? error.message : String(error)
3065
+ });
3066
+ throw new Error(
3067
+ "Unable to connect to Anthropic API. Please check your internet connection and try again."
3068
+ );
3069
+ }
3070
+ }
3071
+ async function verifyApiKey(apiKey, baseURL, provider) {
3072
+ if (!apiKey) {
3073
+ return false;
3074
+ }
3075
+ if (provider && provider !== "anthropic") {
3076
+ try {
3077
+ const headers = {
3078
+ Authorization: `Bearer ${apiKey}`,
3079
+ "Content-Type": "application/json"
3080
+ };
3081
+ if (!baseURL) {
3082
+ debug.warn("API_VERIFICATION_MISSING_BASE_URL", { provider });
3083
+ return false;
3084
+ }
3085
+ const modelsURL = `${baseURL.replace(/\/+$/, "")}/models`;
3086
+ const response = await fetch(modelsURL, {
3087
+ method: "GET",
3088
+ headers
3089
+ });
3090
+ return response.ok;
3091
+ } catch (error) {
3092
+ logError(error);
3093
+ debug.warn("API_VERIFICATION_FAILED", {
3094
+ provider,
3095
+ error: error instanceof Error ? error.message : String(error)
3096
+ });
3097
+ return false;
3098
+ }
3099
+ }
3100
+ const clientConfig = {
3101
+ apiKey,
3102
+ dangerouslyAllowBrowser: true,
3103
+ maxRetries: 3,
3104
+ defaultHeaders: {
3105
+ "User-Agent": USER_AGENT
3106
+ }
3107
+ };
3108
+ if (baseURL && (provider === "anthropic" || provider === "minimax-coding")) {
3109
+ clientConfig.baseURL = baseURL;
3110
+ }
3111
+ const anthropic = new Anthropic3(clientConfig);
3112
+ try {
3113
+ await withRetry(
3114
+ async () => {
3115
+ const model = "claude-sonnet-4-20250514";
3116
+ const messages = [{ role: "user", content: "test" }];
3117
+ await anthropic.messages.create({
3118
+ model,
3119
+ max_tokens: 1e3,
3120
+ // Simple test token limit for API verification
3121
+ messages,
3122
+ temperature: 0
3123
+ });
3124
+ return true;
2947
3125
  },
2948
- { signal }
3126
+ { maxRetries: 2 }
3127
+ // Use fewer retries for API key verification
2949
3128
  );
3129
+ return true;
2950
3130
  } catch (error) {
2951
3131
  logError(error);
2952
- return getAssistantMessageFromError(error);
3132
+ if (error instanceof Error && error.message.includes(
3133
+ '{"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"}}'
3134
+ )) {
3135
+ return false;
3136
+ }
3137
+ throw error;
2953
3138
  }
2954
- const durationMs = Date.now() - start;
2955
- const durationMsIncludingRetries = Date.now() - startIncludingRetries;
2956
- const assistantMessage = queryResult.assistantMessage;
2957
- assistantMessage.message.content = normalizeContentFromAPI(
2958
- assistantMessage.message.content || []
2959
- );
2960
- const normalizedUsage = normalizeUsage(assistantMessage.message.usage);
2961
- assistantMessage.message.usage = normalizedUsage;
2962
- const inputTokens = normalizedUsage.input_tokens ?? 0;
2963
- const outputTokens = normalizedUsage.output_tokens ?? 0;
2964
- const cacheReadInputTokens = normalizedUsage.cache_read_input_tokens ?? 0;
2965
- const cacheCreationInputTokens = normalizedUsage.cache_creation_input_tokens ?? 0;
2966
- const costUSD = inputTokens / 1e6 * SONNET_COST_PER_MILLION_INPUT_TOKENS + outputTokens / 1e6 * SONNET_COST_PER_MILLION_OUTPUT_TOKENS + cacheReadInputTokens / 1e6 * SONNET_COST_PER_MILLION_PROMPT_CACHE_READ_TOKENS + cacheCreationInputTokens / 1e6 * SONNET_COST_PER_MILLION_PROMPT_CACHE_WRITE_TOKENS;
2967
- addToTotalCost(costUSD, durationMsIncludingRetries);
2968
- logLLMInteraction({
2969
- systemPrompt: systemPrompt.join("\n"),
2970
- messages: [...openaiSystem, ...openaiMessages],
2971
- response: assistantMessage.message || queryResult.rawResponse,
2972
- usage: {
2973
- inputTokens,
2974
- outputTokens
2975
- },
2976
- timing: {
2977
- start,
2978
- end: Date.now()
2979
- },
2980
- apiFormat: queryResult.apiFormat
2981
- });
2982
- assistantMessage.costUSD = costUSD;
2983
- assistantMessage.durationMs = durationMs;
2984
- assistantMessage.uuid = assistantMessage.uuid || randomUUID();
2985
- return assistantMessage;
2986
3139
  }
2987
- function getMaxTokensFromProfile(modelProfile) {
2988
- return modelProfile?.maxTokens || 8e3;
2989
- }
2990
- function buildAssistantMessageFromUnifiedResponse(unifiedResponse, startTime) {
2991
- const contentBlocks = [...unifiedResponse.content || []];
2992
- if (unifiedResponse.toolCalls && unifiedResponse.toolCalls.length > 0) {
2993
- for (const toolCall of unifiedResponse.toolCalls) {
2994
- const tool = toolCall.function;
2995
- const toolName = tool?.name;
2996
- let toolArgs = {};
2997
- try {
2998
- toolArgs = tool?.arguments ? JSON.parse(tool.arguments) : {};
2999
- } catch (e) {
3000
- }
3001
- contentBlocks.push({
3002
- type: "tool_use",
3003
- input: toolArgs,
3004
- name: toolName,
3005
- id: toolCall.id?.length > 0 ? toolCall.id : nanoid()
3006
- });
3140
+
3141
+ // packages/core/src/ai/llm.ts
3142
+ async function queryLLM(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
3143
+ const modelManager = options.__testModelManager ?? getModelManager();
3144
+ const modelResolution = modelManager.resolveModelWithInfo(options.model);
3145
+ if (!modelResolution.success || !modelResolution.profile) {
3146
+ const fallbackProfile = modelManager.resolveModel(options.model);
3147
+ if (!fallbackProfile) {
3148
+ throw new Error(
3149
+ modelResolution.error || `Failed to resolve model: ${options.model}`
3150
+ );
3007
3151
  }
3152
+ debug.warn("MODEL_RESOLUTION_FALLBACK", {
3153
+ inputParam: options.model,
3154
+ error: modelResolution.error,
3155
+ fallbackModelName: fallbackProfile.modelName,
3156
+ fallbackProvider: fallbackProfile.provider,
3157
+ requestId: getCurrentRequest()?.id
3158
+ });
3159
+ modelResolution.success = true;
3160
+ modelResolution.profile = fallbackProfile;
3008
3161
  }
3009
- return {
3010
- type: "assistant",
3011
- message: {
3012
- role: "assistant",
3013
- content: contentBlocks,
3014
- usage: {
3015
- input_tokens: unifiedResponse.usage?.promptTokens ?? unifiedResponse.usage?.input_tokens ?? 0,
3016
- output_tokens: unifiedResponse.usage?.completionTokens ?? unifiedResponse.usage?.output_tokens ?? 0,
3017
- prompt_tokens: unifiedResponse.usage?.promptTokens ?? unifiedResponse.usage?.input_tokens ?? 0,
3018
- completion_tokens: unifiedResponse.usage?.completionTokens ?? unifiedResponse.usage?.output_tokens ?? 0,
3019
- promptTokens: unifiedResponse.usage?.promptTokens ?? unifiedResponse.usage?.input_tokens ?? 0,
3020
- completionTokens: unifiedResponse.usage?.completionTokens ?? unifiedResponse.usage?.output_tokens ?? 0,
3021
- totalTokens: unifiedResponse.usage?.totalTokens ?? (unifiedResponse.usage?.promptTokens ?? unifiedResponse.usage?.input_tokens ?? 0) + (unifiedResponse.usage?.completionTokens ?? unifiedResponse.usage?.output_tokens ?? 0)
3022
- }
3023
- },
3024
- costUSD: 0,
3025
- durationMs: Date.now() - startTime,
3026
- uuid: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
3027
- responseId: unifiedResponse.responseId
3028
- };
3029
- }
3030
- function normalizeUsage(usage) {
3031
- if (!usage) {
3032
- return {
3033
- input_tokens: 0,
3034
- output_tokens: 0,
3035
- cache_read_input_tokens: 0,
3036
- cache_creation_input_tokens: 0
3162
+ const modelProfile = modelResolution.profile;
3163
+ const resolvedModel = modelProfile.modelName;
3164
+ const toolUseContext = options.toolUseContext;
3165
+ if (toolUseContext && !toolUseContext.responseState) {
3166
+ const conversationId = getConversationId(
3167
+ toolUseContext.agentId,
3168
+ toolUseContext.messageId
3169
+ );
3170
+ const previousResponseId = responseStateManager.getPreviousResponseId(conversationId);
3171
+ toolUseContext.responseState = {
3172
+ previousResponseId,
3173
+ conversationId
3037
3174
  };
3038
3175
  }
3039
- const inputTokens = usage.input_tokens ?? usage.prompt_tokens ?? usage.inputTokens ?? 0;
3040
- const outputTokens = usage.output_tokens ?? usage.completion_tokens ?? usage.outputTokens ?? 0;
3041
- const cacheReadInputTokens = usage.cache_read_input_tokens ?? usage.prompt_token_details?.cached_tokens ?? usage.cacheReadInputTokens ?? 0;
3042
- const cacheCreationInputTokens = usage.cache_creation_input_tokens ?? usage.cacheCreatedInputTokens ?? 0;
3043
- return {
3044
- ...usage,
3045
- input_tokens: inputTokens,
3046
- output_tokens: outputTokens,
3047
- cache_read_input_tokens: cacheReadInputTokens,
3048
- cache_creation_input_tokens: cacheCreationInputTokens
3049
- };
3050
- }
3051
- function getModelInputTokenCostUSD(model) {
3052
- for (const providerModels of Object.values(models_default)) {
3053
- const modelInfo = providerModels.find((m) => m.model === model);
3054
- if (modelInfo) {
3055
- return modelInfo.input_cost_per_token || 0;
3176
+ debug.api("MODEL_RESOLVED", {
3177
+ inputParam: options.model,
3178
+ resolvedModelName: resolvedModel,
3179
+ provider: modelProfile.provider,
3180
+ isPointer: ["main", "task", "compact", "quick"].includes(options.model),
3181
+ hasResponseState: !!toolUseContext?.responseState,
3182
+ conversationId: toolUseContext?.responseState?.conversationId,
3183
+ requestId: getCurrentRequest()?.id
3184
+ });
3185
+ const currentRequest = getCurrentRequest();
3186
+ debug.api("LLM_REQUEST_START", {
3187
+ messageCount: messages.length,
3188
+ systemPromptLength: systemPrompt.join(" ").length,
3189
+ toolCount: tools.length,
3190
+ model: resolvedModel,
3191
+ originalModelParam: options.model,
3192
+ requestId: getCurrentRequest()?.id
3193
+ });
3194
+ markPhase("LLM_CALL");
3195
+ try {
3196
+ const queryFn = options.__testQueryLLMWithPromptCaching ?? queryLLMWithPromptCaching;
3197
+ const cleanOptions = { ...options };
3198
+ delete cleanOptions.__testModelManager;
3199
+ delete cleanOptions.__testQueryLLMWithPromptCaching;
3200
+ const runQuery = () => queryFn(
3201
+ messages,
3202
+ systemPrompt,
3203
+ maxThinkingTokens,
3204
+ tools,
3205
+ signal,
3206
+ {
3207
+ ...cleanOptions,
3208
+ model: resolvedModel,
3209
+ modelProfile,
3210
+ toolUseContext
3211
+ }
3212
+ // Pass resolved ModelProfile and toolUseContext
3213
+ );
3214
+ const result = options.__testQueryLLMWithPromptCaching ? await runQuery() : await withVCR(messages, runQuery);
3215
+ debug.api("LLM_REQUEST_SUCCESS", {
3216
+ costUSD: result.costUSD,
3217
+ durationMs: result.durationMs,
3218
+ responseLength: result.message.content?.length || 0,
3219
+ requestId: getCurrentRequest()?.id
3220
+ });
3221
+ if (toolUseContext?.responseState?.conversationId && result.responseId) {
3222
+ responseStateManager.setPreviousResponseId(
3223
+ toolUseContext.responseState.conversationId,
3224
+ result.responseId
3225
+ );
3226
+ debug.api("RESPONSE_STATE_UPDATED", {
3227
+ conversationId: toolUseContext.responseState.conversationId,
3228
+ responseId: result.responseId,
3229
+ requestId: getCurrentRequest()?.id
3230
+ });
3056
3231
  }
3232
+ return result;
3233
+ } catch (error) {
3234
+ logErrorWithDiagnosis(
3235
+ error,
3236
+ {
3237
+ messageCount: messages.length,
3238
+ systemPromptLength: systemPrompt.join(" ").length,
3239
+ model: options.model,
3240
+ toolCount: tools.length,
3241
+ phase: "LLM_CALL"
3242
+ },
3243
+ currentRequest?.id
3244
+ );
3245
+ throw error;
3057
3246
  }
3058
- return 3e-6;
3059
3247
  }
3060
- function getModelOutputTokenCostUSD(model) {
3061
- for (const providerModels of Object.values(models_default)) {
3062
- const modelInfo = providerModels.find((m) => m.model === model);
3063
- if (modelInfo) {
3064
- return modelInfo.output_cost_per_token || 0;
3065
- }
3248
+ async function queryLLMWithPromptCaching(messages, systemPrompt, maxThinkingTokens, tools, signal, options) {
3249
+ const config = getGlobalConfig();
3250
+ const modelManager = getModelManager();
3251
+ const toolUseContext = options.toolUseContext;
3252
+ const modelProfile = options.modelProfile || modelManager.getModel("main");
3253
+ let provider;
3254
+ if (modelProfile) {
3255
+ provider = modelProfile.provider || config.primaryProvider || "anthropic";
3256
+ } else {
3257
+ provider = config.primaryProvider || "anthropic";
3066
3258
  }
3067
- return 15e-6;
3259
+ if (provider === "anthropic" || provider === "bigdream" || provider === "opendev" || provider === "minimax-coding") {
3260
+ return queryAnthropicNative(
3261
+ messages,
3262
+ systemPrompt,
3263
+ maxThinkingTokens,
3264
+ tools,
3265
+ signal,
3266
+ { ...options, modelProfile, toolUseContext }
3267
+ );
3268
+ }
3269
+ return queryOpenAI(messages, systemPrompt, maxThinkingTokens, tools, signal, {
3270
+ ...options,
3271
+ modelProfile,
3272
+ toolUseContext
3273
+ });
3068
3274
  }
3069
3275
  async function queryModel(modelPointer, messages, systemPrompt = [], signal) {
3070
3276
  return queryLLM(
3071
3277
  messages,
3072
3278
  systemPrompt,
3073
3279
  0,
3280
+ // maxThinkingTokens
3074
3281
  [],
3282
+ // tools
3075
3283
  signal || new AbortController().signal,
3076
3284
  {
3077
3285
  safeMode: false,
@@ -3091,7 +3299,7 @@ async function queryQuick({
3091
3299
  {
3092
3300
  message: { role: "user", content: userPrompt },
3093
3301
  type: "user",
3094
- uuid: randomUUID()
3302
+ uuid: randomUUID4()
3095
3303
  }
3096
3304
  ];
3097
3305
  return queryModel("quick", messages, systemPrompt, signal);