@shareai-lab/kode 2.0.2 → 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.
- package/LICENSE +201 -0
- package/README.md +649 -25
- package/README.zh-CN.md +579 -0
- package/cli-acp.js +3 -17
- package/cli.js +5 -7
- package/dist/chunks/Doctor-M3J7GRTJ.js +12 -0
- package/dist/chunks/LogList-ISWZ6DDD.js +121 -0
- package/dist/chunks/LogList-ISWZ6DDD.js.map +7 -0
- package/dist/chunks/REPL-RQ6LO6S7.js +56 -0
- package/dist/chunks/ResumeConversation-6DMVBEGH.js +56 -0
- package/dist/chunks/agentLoader-FCRG3TFJ.js +31 -0
- package/dist/{agentsValidate-XP3CFN6F.js → chunks/agentsValidate-PEWMYN4Q.js} +97 -69
- package/dist/chunks/agentsValidate-PEWMYN4Q.js.map +7 -0
- package/dist/{ask-3G5H5KD5.js → chunks/ask-D7SOHJ6Z.js} +36 -44
- package/dist/chunks/ask-D7SOHJ6Z.js.map +7 -0
- package/dist/chunks/autoUpdater-CNESBOKO.js +19 -0
- package/dist/{chunk-EH34V7CY.js → chunks/chunk-2JN5MY67.js} +12 -14
- package/dist/chunks/chunk-2JN5MY67.js.map +7 -0
- package/dist/chunks/chunk-2QONJ5MG.js +14 -0
- package/dist/chunks/chunk-2QONJ5MG.js.map +7 -0
- package/dist/chunks/chunk-2WEXPKHH.js +903 -0
- package/dist/chunks/chunk-2WEXPKHH.js.map +7 -0
- package/dist/{chunk-K2MI4TPB.js → chunks/chunk-3BYE3ME6.js} +717 -792
- package/dist/chunks/chunk-3BYE3ME6.js.map +7 -0
- package/dist/chunks/chunk-3JDNWX7W.js +1264 -0
- package/dist/chunks/chunk-3JDNWX7W.js.map +7 -0
- package/dist/chunks/chunk-3OEJVB5A.js +906 -0
- package/dist/chunks/chunk-3OEJVB5A.js.map +7 -0
- package/dist/chunks/chunk-3TNIOEBO.js +369 -0
- package/dist/chunks/chunk-3TNIOEBO.js.map +7 -0
- package/dist/chunks/chunk-4A46ZXMJ.js +67 -0
- package/dist/chunks/chunk-4A46ZXMJ.js.map +7 -0
- package/dist/{chunk-4GAIJGRH.js → chunks/chunk-4ATBQOFO.js} +107 -55
- package/dist/chunks/chunk-4ATBQOFO.js.map +7 -0
- package/dist/chunks/chunk-4CRUCZR4.js +0 -0
- package/dist/{chunk-54DNHKOD.js → chunks/chunk-4EO6SIQY.js} +32 -75
- package/dist/chunks/chunk-4EO6SIQY.js.map +7 -0
- package/dist/chunks/chunk-53M46S5I.js +64 -0
- package/dist/chunks/chunk-53M46S5I.js.map +7 -0
- package/dist/{chunk-JC6NCUG5.js → chunks/chunk-54KOYG5C.js} +0 -2
- package/dist/{chunk-EZXMVTDU.js → chunks/chunk-6BAS4WY6.js} +29 -45
- package/dist/chunks/chunk-6BAS4WY6.js.map +7 -0
- package/dist/{chunk-BHGTA6JQ.js → chunks/chunk-6KRRFSDN.js} +4 -6
- package/dist/chunks/chunk-6KRRFSDN.js.map +7 -0
- package/dist/chunks/chunk-6LJNZK4K.js +39 -0
- package/dist/chunks/chunk-6LJNZK4K.js.map +7 -0
- package/dist/chunks/chunk-6ZWEOSEI.js +666 -0
- package/dist/chunks/chunk-6ZWEOSEI.js.map +7 -0
- package/dist/chunks/chunk-77XDJMBP.js +3326 -0
- package/dist/chunks/chunk-77XDJMBP.js.map +7 -0
- package/dist/chunks/chunk-7RRW4NTB.js +6454 -0
- package/dist/chunks/chunk-7RRW4NTB.js.map +7 -0
- package/dist/chunks/chunk-7X3TW4JB.js +4520 -0
- package/dist/chunks/chunk-7X3TW4JB.js.map +7 -0
- package/dist/chunks/chunk-B3MW3YGY.js +1409 -0
- package/dist/chunks/chunk-B3MW3YGY.js.map +7 -0
- package/dist/chunks/chunk-BBJFHTBC.js +28 -0
- package/dist/chunks/chunk-BBJFHTBC.js.map +7 -0
- package/dist/chunks/chunk-BHDHXOXB.js +24 -0
- package/dist/chunks/chunk-BHDHXOXB.js.map +7 -0
- package/dist/{chunk-OZNRLY3E.js → chunks/chunk-BTA7SZ26.js} +152 -223
- package/dist/chunks/chunk-BTA7SZ26.js.map +7 -0
- package/dist/chunks/chunk-CDGRYGPZ.js +103 -0
- package/dist/chunks/chunk-CDGRYGPZ.js.map +7 -0
- package/dist/{chunk-S6HRABTA.js → chunks/chunk-CP6E5UG6.js} +1 -4
- package/dist/chunks/chunk-CP6E5UG6.js.map +7 -0
- package/dist/{chunk-2PMO2FS2.js → chunks/chunk-DQ4JHXMT.js} +462 -424
- package/dist/chunks/chunk-DQ4JHXMT.js.map +7 -0
- package/dist/chunks/chunk-DXD76CMV.js +208 -0
- package/dist/chunks/chunk-DXD76CMV.js.map +7 -0
- package/dist/chunks/chunk-GCQCAXJZ.js +0 -0
- package/dist/chunks/chunk-GELCZWMB.js +42 -0
- package/dist/chunks/chunk-GELCZWMB.js.map +7 -0
- package/dist/{chunk-NQLEUHMS.js → chunks/chunk-HJYOH4HC.js} +23 -18
- package/dist/chunks/chunk-HJYOH4HC.js.map +7 -0
- package/dist/chunks/chunk-HPYNW6TT.js +744 -0
- package/dist/chunks/chunk-HPYNW6TT.js.map +7 -0
- package/dist/{chunk-2KWKUXLT.js → chunks/chunk-HRJ3ICQK.js} +59 -55
- package/dist/chunks/chunk-HRJ3ICQK.js.map +7 -0
- package/dist/{chunk-ZQU3TXLC.js → chunks/chunk-IFCIADS3.js} +571 -573
- package/dist/chunks/chunk-IFCIADS3.js.map +7 -0
- package/dist/chunks/chunk-IN7XZ7BC.js +27 -0
- package/dist/chunks/chunk-IN7XZ7BC.js.map +7 -0
- package/dist/chunks/chunk-L7P4M4KW.js +193 -0
- package/dist/chunks/chunk-L7P4M4KW.js.map +7 -0
- package/dist/chunks/chunk-LB6TCPDI.js +0 -0
- package/dist/{chunk-3RUXVV4S.js → chunks/chunk-LOCXPQNJ.js} +1 -4
- package/dist/{chunk-3RUXVV4S.js.map → chunks/chunk-LOCXPQNJ.js.map} +2 -2
- package/dist/{chunk-IE2CG2TV.js → chunks/chunk-LOD5ZHCI.js} +213 -208
- package/dist/chunks/chunk-LOD5ZHCI.js.map +7 -0
- package/dist/{chunk-S3J2TLV6.js → chunks/chunk-M7P3QNRU.js} +1 -4
- package/dist/{chunk-S3J2TLV6.js.map → chunks/chunk-M7P3QNRU.js.map} +2 -2
- package/dist/chunks/chunk-PPHLQVL7.js +4234 -0
- package/dist/chunks/chunk-PPHLQVL7.js.map +7 -0
- package/dist/{chunk-ABLVTESJ.js → chunks/chunk-QAXE37B5.js} +1 -4
- package/dist/chunks/chunk-QAXE37B5.js.map +7 -0
- package/dist/chunks/chunk-QHQOBUF6.js +60 -0
- package/dist/chunks/chunk-QHQOBUF6.js.map +7 -0
- package/dist/{chunk-SRZZFAS7.js → chunks/chunk-RPJXO7GG.js} +241 -214
- package/dist/chunks/chunk-RPJXO7GG.js.map +7 -0
- package/dist/{chunk-NPFOMITO.js → chunks/chunk-SWQV4KSY.js} +1 -4
- package/dist/{chunk-NPFOMITO.js.map → chunks/chunk-SWQV4KSY.js.map} +2 -2
- package/dist/chunks/chunk-SZLAPULP.js +28 -0
- package/dist/chunks/chunk-SZLAPULP.js.map +7 -0
- package/dist/{chunk-SDGKPKDK.js → chunks/chunk-T7RB5V5J.js} +23 -25
- package/dist/chunks/chunk-T7RB5V5J.js.map +7 -0
- package/dist/{chunk-HN4E4UUQ.js → chunks/chunk-TI2CTTMA.js} +25 -17
- package/dist/chunks/chunk-TI2CTTMA.js.map +7 -0
- package/dist/{chunk-G6I7XROM.js → chunks/chunk-TNGVRTO5.js} +45 -20
- package/dist/chunks/chunk-TNGVRTO5.js.map +7 -0
- package/dist/chunks/chunk-TNWB3U5Y.js +2077 -0
- package/dist/chunks/chunk-TNWB3U5Y.js.map +7 -0
- package/dist/chunks/chunk-U2IHWPCU.js +12 -0
- package/dist/chunks/chunk-U2IHWPCU.js.map +7 -0
- package/dist/{chunk-KAA5BGMQ.js → chunks/chunk-UNOY3VJ2.js} +1 -4
- package/dist/{chunk-KAA5BGMQ.js.map → chunks/chunk-UNOY3VJ2.js.map} +2 -2
- package/dist/{chunk-3TXNP6HH.js → chunks/chunk-UVDJL6ZZ.js} +97 -58
- package/dist/chunks/chunk-UVDJL6ZZ.js.map +7 -0
- package/dist/chunks/chunk-VNCW4C2Z.js +13452 -0
- package/dist/chunks/chunk-VNCW4C2Z.js.map +7 -0
- package/dist/chunks/chunk-W5EGGA44.js +15 -0
- package/dist/chunks/chunk-W5EGGA44.js.map +7 -0
- package/dist/chunks/chunk-XR2W3MAM.js +1533 -0
- package/dist/chunks/chunk-XR2W3MAM.js.map +7 -0
- package/dist/{chunk-QYFKRZQC.js → chunks/chunk-YIO5EBMQ.js} +423 -377
- package/dist/chunks/chunk-YIO5EBMQ.js.map +7 -0
- package/dist/chunks/chunk-ZBVLKZ5V.js +1062 -0
- package/dist/chunks/chunk-ZBVLKZ5V.js.map +7 -0
- package/dist/{chunk-E6YNABER.js → chunks/chunk-ZCLTZIVP.js} +1 -4
- package/dist/chunks/chunk-ZCLTZIVP.js.map +7 -0
- package/dist/chunks/client-SILZNM5N.js +42 -0
- package/dist/{config-6ZMBCL23.js → chunks/config-25HRTPSP.js} +48 -10
- package/dist/chunks/cost-tracker-Z2UZT2J5.js +28 -0
- package/dist/{customCommands-DNEJS3ZU.js → chunks/customCommands-TYMYZRG5.js} +11 -8
- package/dist/chunks/engine-MRVF6FK6.js +39 -0
- package/dist/{env-OFAXZ3XG.js → chunks/env-TJ5NOBEB.js} +7 -5
- package/dist/{kodeAgentSessionId-X6XWQW7B.js → chunks/kodeAgentSessionId-VTNISJ2L.js} +2 -4
- package/dist/chunks/kodeAgentSessionLoad-YB2RKBGJ.js +15 -0
- package/dist/chunks/kodeAgentSessionResume-DZSIVKVA.js +13 -0
- package/dist/chunks/kodeAgentStreamJson-X5PLS2S6.js +11 -0
- package/dist/{kodeAgentStreamJsonSession-GRWG3SPE.js → chunks/kodeAgentStreamJsonSession-RDXM4XYF.js} +38 -24
- package/dist/chunks/kodeAgentStreamJsonSession-RDXM4XYF.js.map +7 -0
- package/dist/{chunk-4RTX4AG4.js → chunks/kodeAgentStructuredStdio-SVGDSB4P.js} +14 -9
- package/dist/chunks/kodeAgentStructuredStdio-SVGDSB4P.js.map +7 -0
- package/dist/{kodeHooks-TDMXFWSO.js → chunks/kodeHooks-RVKYRJHG.js} +11 -9
- package/dist/{llm-XVXWYOHK.js → chunks/llm-62N6T5ZT.js} +1734 -1526
- package/dist/chunks/llm-62N6T5ZT.js.map +7 -0
- package/dist/chunks/llmLazy-ZUSSE3ZA.js +13 -0
- package/dist/{mentionProcessor-YD7YXYGF.js → chunks/mentionProcessor-RJW5UPJD.js} +46 -16
- package/dist/chunks/mentionProcessor-RJW5UPJD.js.map +7 -0
- package/dist/{messages-OFUJSPRV.js → chunks/messages-EEWWLPHN.js} +2 -6
- package/dist/chunks/model-5TIEKQPD.js +37 -0
- package/dist/{openai-5G5D5Q4B.js → chunks/openai-XXK3YZG4.js} +13 -10
- package/dist/{outputStyles-HLDXFQK3.js → chunks/outputStyles-FAJTXN2A.js} +6 -9
- package/dist/chunks/permissions-HO7INPWM.js +27 -0
- package/dist/{pluginRuntime-FPTKK6NY.js → chunks/pluginRuntime-C7K5ULK2.js} +31 -48
- package/dist/chunks/pluginRuntime-C7K5ULK2.js.map +7 -0
- package/dist/chunks/pluginValidation-DAM7WRTC.js +20 -0
- package/dist/chunks/registry-XYJXMOA5.js +60 -0
- package/dist/chunks/responsesStreaming-JNGE2P3D.js +8 -0
- package/dist/chunks/runNonTextPrintMode-SVBLCZQX.js +577 -0
- package/dist/chunks/runNonTextPrintMode-SVBLCZQX.js.map +7 -0
- package/dist/chunks/server-REXXF5IK.js +46 -0
- package/dist/{skillMarketplace-PSNKDINM.js → chunks/skillMarketplace-N4HVHNST.js} +8 -6
- package/dist/chunks/src-OROQIWP3.js +44 -0
- package/dist/chunks/src-QXLGGMUW.js +1647 -0
- package/dist/chunks/src-QXLGGMUW.js.map +7 -0
- package/dist/{cli-SRV2INSL.js → chunks/src-SSDT6MVP.js} +2659 -3384
- package/dist/chunks/src-SSDT6MVP.js.map +7 -0
- package/dist/chunks/theme-YBJUIMWK.js +10 -0
- package/dist/{toolPermissionContext-65L65VEZ.js → chunks/toolPermissionContext-MOCTRR7N.js} +2 -4
- package/dist/chunks/toolPermissionSettings-EV2EJAXL.js +18 -0
- package/dist/chunks/toolPermissionSettings-EV2EJAXL.js.map +7 -0
- package/dist/chunks/uuid-6577SO6X.js +7 -0
- package/dist/chunks/uuid-6577SO6X.js.map +7 -0
- package/dist/chunks/webOnlyMode-ALXX7UQY.js +66 -0
- package/dist/chunks/webOnlyMode-ALXX7UQY.js.map +7 -0
- package/dist/entrypoints/cli.js +10 -0
- package/dist/entrypoints/cli.js.map +7 -0
- package/dist/entrypoints/daemon.js +10 -0
- package/dist/entrypoints/daemon.js.map +7 -0
- package/dist/entrypoints/mcp.js +71 -0
- package/dist/entrypoints/mcp.js.map +7 -0
- package/dist/index.js +6 -7
- package/dist/index.js.map +3 -3
- package/dist/sdk/client.cjs +391 -0
- package/dist/sdk/client.cjs.map +7 -0
- package/dist/sdk/client.js +364 -0
- package/dist/sdk/client.js.map +7 -0
- package/dist/sdk/core.cjs +19932 -0
- package/dist/sdk/core.cjs.map +7 -0
- package/dist/sdk/core.js +19893 -0
- package/dist/sdk/core.js.map +7 -0
- package/dist/sdk/daemon-client.cjs +257 -0
- package/dist/sdk/daemon-client.cjs.map +7 -0
- package/dist/sdk/daemon-client.js +221 -0
- package/dist/sdk/daemon-client.js.map +7 -0
- package/dist/sdk/protocol.cjs +170 -0
- package/dist/sdk/protocol.cjs.map +7 -0
- package/dist/sdk/protocol.js +140 -0
- package/dist/sdk/protocol.js.map +7 -0
- package/dist/sdk/runtime-node.cjs +236 -0
- package/dist/sdk/runtime-node.cjs.map +7 -0
- package/dist/sdk/runtime-node.js +222 -0
- package/dist/sdk/runtime-node.js.map +7 -0
- package/dist/sdk/runtime.cjs +17 -0
- package/dist/sdk/runtime.cjs.map +7 -0
- package/dist/sdk/runtime.js +0 -0
- package/dist/sdk/runtime.js.map +7 -0
- package/dist/sdk/tools.cjs +30300 -0
- package/dist/sdk/tools.cjs.map +7 -0
- package/dist/sdk/tools.js +30282 -0
- package/dist/sdk/tools.js.map +7 -0
- package/dist/webui/assets/index-5hlfByVS.css +1 -0
- package/dist/webui/assets/index-BR9lm1lA.js +82 -0
- package/dist/webui/index.html +28 -0
- package/package.json +93 -22
- package/scripts/binary-utils.cjs +12 -4
- package/scripts/cli-acp-wrapper.cjs +3 -17
- package/scripts/cli-wrapper.cjs +5 -7
- package/scripts/postinstall.js +8 -4
- package/dist/REPL-GIU4ZIXM.js +0 -42
- package/dist/acp-H3VJ77YG.js +0 -1357
- package/dist/acp-H3VJ77YG.js.map +0 -7
- package/dist/agentsValidate-XP3CFN6F.js.map +0 -7
- package/dist/ask-3G5H5KD5.js.map +0 -7
- package/dist/autoUpdater-DNRMJWFQ.js +0 -17
- package/dist/chunk-2KWKUXLT.js.map +0 -7
- package/dist/chunk-2PMO2FS2.js.map +0 -7
- package/dist/chunk-3TXNP6HH.js.map +0 -7
- package/dist/chunk-4GAIJGRH.js.map +0 -7
- package/dist/chunk-4RTX4AG4.js.map +0 -7
- package/dist/chunk-54DNHKOD.js.map +0 -7
- package/dist/chunk-67PY5IX6.js +0 -34
- package/dist/chunk-67PY5IX6.js.map +0 -7
- package/dist/chunk-6DRDLOLP.js +0 -2613
- package/dist/chunk-6DRDLOLP.js.map +0 -7
- package/dist/chunk-7CQVZNQV.js +0 -1609
- package/dist/chunk-7CQVZNQV.js.map +0 -7
- package/dist/chunk-ABLVTESJ.js.map +0 -7
- package/dist/chunk-AIMIPK4B.js +0 -835
- package/dist/chunk-AIMIPK4B.js.map +0 -7
- package/dist/chunk-BHGTA6JQ.js.map +0 -7
- package/dist/chunk-CIG63V4E.js +0 -72
- package/dist/chunk-CIG63V4E.js.map +0 -7
- package/dist/chunk-E6YNABER.js.map +0 -7
- package/dist/chunk-EH34V7CY.js.map +0 -7
- package/dist/chunk-EZXMVTDU.js.map +0 -7
- package/dist/chunk-FH5CHM6L.js +0 -148
- package/dist/chunk-FH5CHM6L.js.map +0 -7
- package/dist/chunk-G6I7XROM.js.map +0 -7
- package/dist/chunk-HN4E4UUQ.js.map +0 -7
- package/dist/chunk-HSPVVDIW.js +0 -30198
- package/dist/chunk-HSPVVDIW.js.map +0 -7
- package/dist/chunk-IE2CG2TV.js.map +0 -7
- package/dist/chunk-K2MI4TPB.js.map +0 -7
- package/dist/chunk-MN77D2F7.js +0 -2931
- package/dist/chunk-MN77D2F7.js.map +0 -7
- package/dist/chunk-NQLEUHMS.js.map +0 -7
- package/dist/chunk-OIFQB3S4.js +0 -515
- package/dist/chunk-OIFQB3S4.js.map +0 -7
- package/dist/chunk-OWTG2W3A.js +0 -164
- package/dist/chunk-OWTG2W3A.js.map +0 -7
- package/dist/chunk-OZNRLY3E.js.map +0 -7
- package/dist/chunk-QYFKRZQC.js.map +0 -7
- package/dist/chunk-S6HRABTA.js.map +0 -7
- package/dist/chunk-SDGKPKDK.js.map +0 -7
- package/dist/chunk-SRZZFAS7.js.map +0 -7
- package/dist/chunk-UKHTVRJM.js +0 -47
- package/dist/chunk-UKHTVRJM.js.map +0 -7
- package/dist/chunk-UYXEDKOZ.js +0 -24
- package/dist/chunk-UYXEDKOZ.js.map +0 -7
- package/dist/chunk-VBXVYQYY.js +0 -145
- package/dist/chunk-VBXVYQYY.js.map +0 -7
- package/dist/chunk-WVHORZQ5.js +0 -17
- package/dist/chunk-WVHORZQ5.js.map +0 -7
- package/dist/chunk-WWUWDNWW.js +0 -49
- package/dist/chunk-WWUWDNWW.js.map +0 -7
- package/dist/chunk-Z33T5YN5.js +0 -654
- package/dist/chunk-Z33T5YN5.js.map +0 -7
- package/dist/chunk-ZQU3TXLC.js.map +0 -7
- package/dist/cli-SRV2INSL.js.map +0 -7
- package/dist/commands-TWH6PGVG.js +0 -46
- package/dist/context-JQIOOI4W.js +0 -30
- package/dist/costTracker-6SL26FDB.js +0 -19
- package/dist/kodeAgentSessionLoad-6N27AC5K.js +0 -18
- package/dist/kodeAgentSessionResume-HUSAEO24.js +0 -16
- package/dist/kodeAgentStreamJson-NXFN7TXH.js +0 -13
- package/dist/kodeAgentStreamJsonSession-GRWG3SPE.js.map +0 -7
- package/dist/kodeAgentStructuredStdio-HGWJT7CU.js +0 -10
- package/dist/llm-XVXWYOHK.js.map +0 -7
- package/dist/llmLazy-7TD5N7XP.js +0 -15
- package/dist/loader-AUXIJTY6.js +0 -28
- package/dist/mcp-BXJ3K7NZ.js +0 -49
- package/dist/mentionProcessor-YD7YXYGF.js.map +0 -7
- package/dist/model-KPYCXWBK.js +0 -30
- package/dist/pluginRuntime-FPTKK6NY.js.map +0 -7
- package/dist/pluginValidation-DSFXZ4GF.js +0 -17
- package/dist/prompts-LWLAJRS2.js +0 -48
- package/dist/query-HVPWL27C.js +0 -50
- package/dist/responsesStreaming-AW344PQO.js +0 -10
- package/dist/ripgrep-YOPCY2GO.js +0 -17
- package/dist/state-KNRWP3FO.js +0 -16
- package/dist/theme-7S2QN2FO.js +0 -14
- package/dist/toolPermissionSettings-GPOBH4IV.js +0 -18
- package/dist/tools-FZU2FZBD.js +0 -47
- package/dist/userInput-VHNBN2MW.js +0 -311
- package/dist/userInput-VHNBN2MW.js.map +0 -7
- package/dist/uuid-QN2CNKKN.js +0 -9
- /package/dist/{REPL-GIU4ZIXM.js.map → chunks/Doctor-M3J7GRTJ.js.map} +0 -0
- /package/dist/{autoUpdater-DNRMJWFQ.js.map → chunks/REPL-RQ6LO6S7.js.map} +0 -0
- /package/dist/{chunk-JC6NCUG5.js.map → chunks/ResumeConversation-6DMVBEGH.js.map} +0 -0
- /package/dist/{commands-TWH6PGVG.js.map → chunks/agentLoader-FCRG3TFJ.js.map} +0 -0
- /package/dist/{config-6ZMBCL23.js.map → chunks/autoUpdater-CNESBOKO.js.map} +0 -0
- /package/dist/{context-JQIOOI4W.js.map → chunks/chunk-4CRUCZR4.js.map} +0 -0
- /package/dist/{costTracker-6SL26FDB.js.map → chunks/chunk-54KOYG5C.js.map} +0 -0
- /package/dist/{customCommands-DNEJS3ZU.js.map → chunks/chunk-GCQCAXJZ.js.map} +0 -0
- /package/dist/{env-OFAXZ3XG.js.map → chunks/chunk-LB6TCPDI.js.map} +0 -0
- /package/dist/{kodeAgentSessionId-X6XWQW7B.js.map → chunks/client-SILZNM5N.js.map} +0 -0
- /package/dist/{kodeAgentSessionLoad-6N27AC5K.js.map → chunks/config-25HRTPSP.js.map} +0 -0
- /package/dist/{kodeAgentSessionResume-HUSAEO24.js.map → chunks/cost-tracker-Z2UZT2J5.js.map} +0 -0
- /package/dist/{kodeAgentStreamJson-NXFN7TXH.js.map → chunks/customCommands-TYMYZRG5.js.map} +0 -0
- /package/dist/{kodeAgentStructuredStdio-HGWJT7CU.js.map → chunks/engine-MRVF6FK6.js.map} +0 -0
- /package/dist/{kodeHooks-TDMXFWSO.js.map → chunks/env-TJ5NOBEB.js.map} +0 -0
- /package/dist/{llmLazy-7TD5N7XP.js.map → chunks/kodeAgentSessionId-VTNISJ2L.js.map} +0 -0
- /package/dist/{loader-AUXIJTY6.js.map → chunks/kodeAgentSessionLoad-YB2RKBGJ.js.map} +0 -0
- /package/dist/{mcp-BXJ3K7NZ.js.map → chunks/kodeAgentSessionResume-DZSIVKVA.js.map} +0 -0
- /package/dist/{messages-OFUJSPRV.js.map → chunks/kodeAgentStreamJson-X5PLS2S6.js.map} +0 -0
- /package/dist/{model-KPYCXWBK.js.map → chunks/kodeHooks-RVKYRJHG.js.map} +0 -0
- /package/dist/{openai-5G5D5Q4B.js.map → chunks/llmLazy-ZUSSE3ZA.js.map} +0 -0
- /package/dist/{outputStyles-HLDXFQK3.js.map → chunks/messages-EEWWLPHN.js.map} +0 -0
- /package/dist/{pluginValidation-DSFXZ4GF.js.map → chunks/model-5TIEKQPD.js.map} +0 -0
- /package/dist/{prompts-LWLAJRS2.js.map → chunks/openai-XXK3YZG4.js.map} +0 -0
- /package/dist/{query-HVPWL27C.js.map → chunks/outputStyles-FAJTXN2A.js.map} +0 -0
- /package/dist/{responsesStreaming-AW344PQO.js.map → chunks/permissions-HO7INPWM.js.map} +0 -0
- /package/dist/{ripgrep-YOPCY2GO.js.map → chunks/pluginValidation-DAM7WRTC.js.map} +0 -0
- /package/dist/{skillMarketplace-PSNKDINM.js.map → chunks/registry-XYJXMOA5.js.map} +0 -0
- /package/dist/{state-KNRWP3FO.js.map → chunks/responsesStreaming-JNGE2P3D.js.map} +0 -0
- /package/dist/{theme-7S2QN2FO.js.map → chunks/server-REXXF5IK.js.map} +0 -0
- /package/dist/{toolPermissionContext-65L65VEZ.js.map → chunks/skillMarketplace-N4HVHNST.js.map} +0 -0
- /package/dist/{toolPermissionSettings-GPOBH4IV.js.map → chunks/src-OROQIWP3.js.map} +0 -0
- /package/dist/{tools-FZU2FZBD.js.map → chunks/theme-YBJUIMWK.js.map} +0 -0
- /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
|
-
|
|
5
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-3TXNP6HH.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-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-54DNHKOD.js";
|
|
30
|
-
import {
|
|
31
|
-
getCompletionWithProfile,
|
|
32
|
-
getGPT5CompletionWithProfile
|
|
33
|
-
} from "./chunk-ZQU3TXLC.js";
|
|
34
|
-
import "./chunk-67PY5IX6.js";
|
|
35
|
-
import "./chunk-OWTG2W3A.js";
|
|
36
|
-
import "./chunk-SRZZFAS7.js";
|
|
37
|
-
import "./chunk-EH34V7CY.js";
|
|
38
|
-
import "./chunk-VBXVYQYY.js";
|
|
39
|
-
import "./chunk-S6HRABTA.js";
|
|
40
|
-
import "./chunk-IE2CG2TV.js";
|
|
41
|
-
import "./chunk-E6YNABER.js";
|
|
42
|
-
import "./chunk-OZNRLY3E.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-
|
|
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-
|
|
61
|
-
import "./chunk-OIFQB3S4.js";
|
|
62
|
-
import "./chunk-SDGKPKDK.js";
|
|
63
|
-
import {
|
|
64
|
-
getAnthropicApiKey,
|
|
65
|
-
getGlobalConfig
|
|
66
|
-
} from "./chunk-AIMIPK4B.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-
|
|
56
|
+
} from "./chunk-YIO5EBMQ.js";
|
|
76
57
|
import {
|
|
77
58
|
PRODUCT_COMMAND,
|
|
78
59
|
env,
|
|
79
|
-
getCwd,
|
|
80
60
|
logError
|
|
81
|
-
} from "./chunk-
|
|
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-
|
|
68
|
+
} from "./chunk-W5EGGA44.js";
|
|
69
|
+
import "./chunk-DXD76CMV.js";
|
|
70
|
+
import "./chunk-LB6TCPDI.js";
|
|
85
71
|
import {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
getAnthropicApiKey,
|
|
73
|
+
getGlobalConfig
|
|
74
|
+
} from "./chunk-XR2W3MAM.js";
|
|
75
|
+
import "./chunk-B3MW3YGY.js";
|
|
76
|
+
import "./chunk-54KOYG5C.js";
|
|
89
77
|
|
|
90
|
-
// src/
|
|
78
|
+
// packages/core/src/ai/llm.ts
|
|
91
79
|
import "@anthropic-ai/sdk/shims/node";
|
|
92
|
-
import
|
|
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/
|
|
100
|
-
|
|
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/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
|
215
|
-
if (
|
|
216
|
-
return
|
|
127
|
+
function shouldRetry(error) {
|
|
128
|
+
if (error.message?.includes('"type":"overloaded_error"')) {
|
|
129
|
+
return process.env.USER_TYPE === "SWE_BENCH";
|
|
217
130
|
}
|
|
218
|
-
const
|
|
219
|
-
if (
|
|
220
|
-
|
|
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
|
|
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
|
|
225
|
-
|
|
226
|
-
|
|
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
|
-
|
|
178
|
+
throw lastError;
|
|
229
179
|
}
|
|
230
180
|
|
|
231
|
-
// src/
|
|
232
|
-
|
|
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/
|
|
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
|
-
//
|
|
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/
|
|
471
|
+
// packages/core/src/ai/adapters/responsesAPI.ts
|
|
467
472
|
import { zodToJsonSchema as zodToJsonSchema2 } from "zod-to-json-schema";
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
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:
|
|
481
|
-
instructions:
|
|
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
|
|
537
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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-
|
|
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/
|
|
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:
|
|
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
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
1395
|
-
function
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
if (
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
}
|
|
1409
|
-
|
|
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
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
if (
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
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({
|
|
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({
|
|
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 ("
|
|
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/
|
|
1677
|
-
function
|
|
1678
|
-
return
|
|
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
|
|
1706
|
-
if (
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
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
|
|
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
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
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
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
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
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
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
|
-
|
|
1757
|
-
} catch (
|
|
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
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
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
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
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 (
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
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
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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
|
-
|
|
1854
|
-
|
|
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
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
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
|
-
|
|
1884
|
-
|
|
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
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
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 :
|
|
1805
|
+
id: toolCall.id?.length > 0 ? toolCall.id : nanoid2()
|
|
2045
1806
|
});
|
|
2046
1807
|
}
|
|
2047
1808
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
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
|
-
|
|
2079
|
-
|
|
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
|
|
2091
|
-
const
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
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
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
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
|
-
|
|
2109
|
-
|
|
2110
|
-
...
|
|
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
|
|
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" &&
|
|
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
|
-
|
|
2175
|
-
|
|
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
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
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
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
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
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
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
|
-
|
|
2315
|
-
|
|
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
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
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
|
-
|
|
2349
|
-
|
|
2350
|
-
const
|
|
2351
|
-
|
|
2352
|
-
|
|
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 (
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
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
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
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
|
-
|
|
2376
|
-
const
|
|
2377
|
-
const
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
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
|
|
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 :
|
|
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 ??
|
|
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 = {
|
|
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
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
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 =
|
|
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:
|
|
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
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
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
|
-
|
|
2715
|
-
|
|
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 (
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
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
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
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 (
|
|
2759
|
-
|
|
2760
|
-
systemPrompt = [getCLISyspromptPrefix() + systemPrompt];
|
|
2854
|
+
if (!existsSync(dirname(filename))) {
|
|
2855
|
+
mkdirSync(dirname(filename), { recursive: true });
|
|
2761
2856
|
}
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
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
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
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
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
if (adapterContext) {
|
|
2845
|
-
if (adapterContext.shouldUseResponses) {
|
|
2846
|
-
const { callGPT5ResponsesAPI } = await import("./openai-5G5D5Q4B.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
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
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
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
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
|
-
|
|
2892
|
-
|
|
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
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
const
|
|
2992
|
-
if (
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
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
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
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
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
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
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
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
|
-
|
|
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:
|
|
3302
|
+
uuid: randomUUID4()
|
|
3095
3303
|
}
|
|
3096
3304
|
];
|
|
3097
3305
|
return queryModel("quick", messages, systemPrompt, signal);
|