@shareai-lab/kode 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-7LH4HTNR.js → chunks/agentsValidate-PEWMYN4Q.js} +97 -69
- package/dist/chunks/agentsValidate-PEWMYN4Q.js.map +7 -0
- package/dist/{ask-3NHFFUQG.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-AFFSCMYS.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-ARZSBOAO.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-UHYRLID6.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-YC6LJCDE.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-3IN27HA5.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-73WGVYLQ.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-QVLYOPO5.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-K2CWOTI2.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-RZWOUA25.js → chunks/chunk-HRJ3ICQK.js} +59 -55
- package/dist/chunks/chunk-HRJ3ICQK.js.map +7 -0
- package/dist/{chunk-DZE5YA7L.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-7M2YN6TU.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-W7GRKO7Q.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-7U7L4NMD.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-ZVDRDPII.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-MWRSY4X6.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-STSX7GIX.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-RUSD6G5Y.js → chunks/config-25HRTPSP.js} +48 -10
- package/dist/chunks/cost-tracker-Z2UZT2J5.js +28 -0
- package/dist/{customCommands-TOIJFZAL.js → chunks/customCommands-TYMYZRG5.js} +11 -8
- package/dist/chunks/engine-MRVF6FK6.js +39 -0
- package/dist/{env-XGKBLU3D.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-UGEZJJEB.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-QWM36A3D.js → chunks/kodeHooks-RVKYRJHG.js} +11 -9
- package/dist/{llm-ZUQC4WYM.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-EE3XFHCJ.js → chunks/mentionProcessor-RJW5UPJD.js} +46 -16
- package/dist/chunks/mentionProcessor-RJW5UPJD.js.map +7 -0
- package/dist/{messages-EOYQKPGM.js → chunks/messages-EEWWLPHN.js} +2 -6
- package/dist/chunks/model-5TIEKQPD.js +37 -0
- package/dist/{openai-RRCWW33N.js → chunks/openai-XXK3YZG4.js} +13 -10
- package/dist/{outputStyles-62Q3VH2J.js → chunks/outputStyles-FAJTXN2A.js} +6 -9
- package/dist/chunks/permissions-HO7INPWM.js +27 -0
- package/dist/{pluginRuntime-6ETCZ2LL.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-3RXQBVOL.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-DOPVY2CW.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-CW7AYLVL.js +0 -42
- package/dist/acp-VEPJ74LT.js +0 -1357
- package/dist/acp-VEPJ74LT.js.map +0 -7
- package/dist/agentsValidate-7LH4HTNR.js.map +0 -7
- package/dist/ask-3NHFFUQG.js.map +0 -7
- package/dist/autoUpdater-ITPIHCOI.js +0 -17
- package/dist/chunk-3IN27HA5.js.map +0 -7
- package/dist/chunk-4FX3IVPT.js +0 -164
- package/dist/chunk-4FX3IVPT.js.map +0 -7
- package/dist/chunk-4RTX4AG4.js.map +0 -7
- package/dist/chunk-5PDP7R6N.js +0 -515
- package/dist/chunk-5PDP7R6N.js.map +0 -7
- package/dist/chunk-73WGVYLQ.js.map +0 -7
- package/dist/chunk-7M2YN6TU.js.map +0 -7
- package/dist/chunk-7U7L4NMD.js.map +0 -7
- package/dist/chunk-ABLVTESJ.js.map +0 -7
- package/dist/chunk-AFFSCMYS.js.map +0 -7
- package/dist/chunk-ARZSBOAO.js.map +0 -7
- package/dist/chunk-CIG63V4E.js +0 -72
- package/dist/chunk-CIG63V4E.js.map +0 -7
- package/dist/chunk-CM3EGTG6.js +0 -1609
- package/dist/chunk-CM3EGTG6.js.map +0 -7
- package/dist/chunk-DZE5YA7L.js.map +0 -7
- package/dist/chunk-E6YNABER.js.map +0 -7
- package/dist/chunk-EZXMVTDU.js.map +0 -7
- package/dist/chunk-F2SJXUDI.js +0 -148
- package/dist/chunk-F2SJXUDI.js.map +0 -7
- package/dist/chunk-FC5ZCKBI.js +0 -30167
- package/dist/chunk-FC5ZCKBI.js.map +0 -7
- package/dist/chunk-HCBELH4J.js +0 -145
- package/dist/chunk-HCBELH4J.js.map +0 -7
- package/dist/chunk-HN4E4UUQ.js.map +0 -7
- package/dist/chunk-IZVMU4S2.js +0 -654
- package/dist/chunk-IZVMU4S2.js.map +0 -7
- package/dist/chunk-K2CWOTI2.js.map +0 -7
- package/dist/chunk-LC4TVOCZ.js +0 -835
- package/dist/chunk-LC4TVOCZ.js.map +0 -7
- package/dist/chunk-MIW7N2MY.js +0 -2613
- package/dist/chunk-MIW7N2MY.js.map +0 -7
- package/dist/chunk-MWRSY4X6.js.map +0 -7
- package/dist/chunk-ND3XWFO6.js +0 -34
- package/dist/chunk-ND3XWFO6.js.map +0 -7
- package/dist/chunk-QVLYOPO5.js.map +0 -7
- package/dist/chunk-RZWOUA25.js.map +0 -7
- package/dist/chunk-S6HRABTA.js.map +0 -7
- package/dist/chunk-STSX7GIX.js.map +0 -7
- package/dist/chunk-UHYRLID6.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-W7GRKO7Q.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-YC6LJCDE.js.map +0 -7
- package/dist/chunk-YXYYDIMI.js +0 -2931
- package/dist/chunk-YXYYDIMI.js.map +0 -7
- package/dist/chunk-ZVDRDPII.js.map +0 -7
- package/dist/cli-DOPVY2CW.js.map +0 -7
- package/dist/commands-2BF2CJ3A.js +0 -46
- package/dist/context-6FXPETYH.js +0 -30
- package/dist/costTracker-6SL26FDB.js +0 -19
- package/dist/kodeAgentSessionLoad-MITZADPB.js +0 -18
- package/dist/kodeAgentSessionResume-GVRWB4WO.js +0 -16
- package/dist/kodeAgentStreamJson-NXFN7TXH.js +0 -13
- package/dist/kodeAgentStreamJsonSession-UGEZJJEB.js.map +0 -7
- package/dist/kodeAgentStructuredStdio-HGWJT7CU.js +0 -10
- package/dist/llm-ZUQC4WYM.js.map +0 -7
- package/dist/llmLazy-54QQHA54.js +0 -15
- package/dist/loader-FYHJQES5.js +0 -28
- package/dist/mcp-J332IKT3.js +0 -49
- package/dist/mentionProcessor-EE3XFHCJ.js.map +0 -7
- package/dist/model-FV3JDJKH.js +0 -30
- package/dist/pluginRuntime-6ETCZ2LL.js.map +0 -7
- package/dist/pluginValidation-I4YKUWGS.js +0 -17
- package/dist/prompts-ZLEKDD77.js +0 -48
- package/dist/query-VFRJPBGD.js +0 -50
- package/dist/responsesStreaming-AW344PQO.js +0 -10
- package/dist/ripgrep-3NTIKQYW.js +0 -17
- package/dist/state-P5G6CO5V.js +0 -16
- package/dist/theme-3LWP3BG7.js +0 -14
- package/dist/toolPermissionSettings-3ROBVTUK.js +0 -18
- package/dist/tools-RO7HSSE5.js +0 -47
- package/dist/userInput-JSBJRFSK.js +0 -311
- package/dist/userInput-JSBJRFSK.js.map +0 -7
- package/dist/uuid-QN2CNKKN.js +0 -9
- /package/dist/{REPL-CW7AYLVL.js.map → chunks/Doctor-M3J7GRTJ.js.map} +0 -0
- /package/dist/{autoUpdater-ITPIHCOI.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-2BF2CJ3A.js.map → chunks/agentLoader-FCRG3TFJ.js.map} +0 -0
- /package/dist/{config-RUSD6G5Y.js.map → chunks/autoUpdater-CNESBOKO.js.map} +0 -0
- /package/dist/{context-6FXPETYH.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-TOIJFZAL.js.map → chunks/chunk-GCQCAXJZ.js.map} +0 -0
- /package/dist/{env-XGKBLU3D.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-MITZADPB.js.map → chunks/config-25HRTPSP.js.map} +0 -0
- /package/dist/{kodeAgentSessionResume-GVRWB4WO.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-QWM36A3D.js.map → chunks/env-TJ5NOBEB.js.map} +0 -0
- /package/dist/{llmLazy-54QQHA54.js.map → chunks/kodeAgentSessionId-VTNISJ2L.js.map} +0 -0
- /package/dist/{loader-FYHJQES5.js.map → chunks/kodeAgentSessionLoad-YB2RKBGJ.js.map} +0 -0
- /package/dist/{mcp-J332IKT3.js.map → chunks/kodeAgentSessionResume-DZSIVKVA.js.map} +0 -0
- /package/dist/{messages-EOYQKPGM.js.map → chunks/kodeAgentStreamJson-X5PLS2S6.js.map} +0 -0
- /package/dist/{model-FV3JDJKH.js.map → chunks/kodeHooks-RVKYRJHG.js.map} +0 -0
- /package/dist/{openai-RRCWW33N.js.map → chunks/llmLazy-ZUSSE3ZA.js.map} +0 -0
- /package/dist/{outputStyles-62Q3VH2J.js.map → chunks/messages-EEWWLPHN.js.map} +0 -0
- /package/dist/{pluginValidation-I4YKUWGS.js.map → chunks/model-5TIEKQPD.js.map} +0 -0
- /package/dist/{prompts-ZLEKDD77.js.map → chunks/openai-XXK3YZG4.js.map} +0 -0
- /package/dist/{query-VFRJPBGD.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-3NTIKQYW.js.map → chunks/pluginValidation-DAM7WRTC.js.map} +0 -0
- /package/dist/{skillMarketplace-3RXQBVOL.js.map → chunks/registry-XYJXMOA5.js.map} +0 -0
- /package/dist/{state-P5G6CO5V.js.map → chunks/responsesStreaming-JNGE2P3D.js.map} +0 -0
- /package/dist/{theme-3LWP3BG7.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-3ROBVTUK.js.map → chunks/src-OROQIWP3.js.map} +0 -0
- /package/dist/{tools-RO7HSSE5.js.map → chunks/theme-YBJUIMWK.js.map} +0 -0
- /package/dist/{uuid-QN2CNKKN.js.map → chunks/toolPermissionContext-MOCTRR7N.js.map} +0 -0
package/dist/chunk-MIW7N2MY.js
DELETED
|
@@ -1,2613 +0,0 @@
|
|
|
1
|
-
import { createRequire as __kodeCreateRequire } from "node:module";
|
|
2
|
-
const require = __kodeCreateRequire(import.meta.url);
|
|
3
|
-
import {
|
|
4
|
-
AskUserQuestionTool,
|
|
5
|
-
BashTool,
|
|
6
|
-
Cost,
|
|
7
|
-
EnterPlanModeTool,
|
|
8
|
-
ExitPlanModeTool,
|
|
9
|
-
FileEditTool,
|
|
10
|
-
FileReadTool,
|
|
11
|
-
FileWriteTool,
|
|
12
|
-
GlobTool,
|
|
13
|
-
GrepTool,
|
|
14
|
-
KillShellTool,
|
|
15
|
-
NotebookEditTool,
|
|
16
|
-
SkillTool,
|
|
17
|
-
SlashCommandTool,
|
|
18
|
-
TodoWriteTool,
|
|
19
|
-
WebFetchTool,
|
|
20
|
-
WebSearchTool,
|
|
21
|
-
applyMarkdown,
|
|
22
|
-
countTokens,
|
|
23
|
-
getAbsolutePath,
|
|
24
|
-
getAgentPrompt,
|
|
25
|
-
getMaxThinkingTokens,
|
|
26
|
-
hasPermissionsToUseTool,
|
|
27
|
-
hasReadPermission,
|
|
28
|
-
query
|
|
29
|
-
} from "./chunk-FC5ZCKBI.js";
|
|
30
|
-
import {
|
|
31
|
-
FallbackToolUseRejectedMessage,
|
|
32
|
-
MCPTool,
|
|
33
|
-
getClients,
|
|
34
|
-
getMCPTools
|
|
35
|
-
} from "./chunk-CM3EGTG6.js";
|
|
36
|
-
import {
|
|
37
|
-
queryLLM
|
|
38
|
-
} from "./chunk-ND3XWFO6.js";
|
|
39
|
-
import {
|
|
40
|
-
generateAgentId
|
|
41
|
-
} from "./chunk-7M2YN6TU.js";
|
|
42
|
-
import {
|
|
43
|
-
getActiveAgents,
|
|
44
|
-
getAgentByType,
|
|
45
|
-
getAvailableAgentTypes
|
|
46
|
-
} from "./chunk-73WGVYLQ.js";
|
|
47
|
-
import {
|
|
48
|
-
INTERRUPT_MESSAGE,
|
|
49
|
-
createAssistantMessage,
|
|
50
|
-
createUserMessage,
|
|
51
|
-
getLastAssistantMessageId
|
|
52
|
-
} from "./chunk-RZWOUA25.js";
|
|
53
|
-
import {
|
|
54
|
-
getModelManager
|
|
55
|
-
} from "./chunk-IZVMU4S2.js";
|
|
56
|
-
import {
|
|
57
|
-
getContext
|
|
58
|
-
} from "./chunk-5PDP7R6N.js";
|
|
59
|
-
import {
|
|
60
|
-
getTheme
|
|
61
|
-
} from "./chunk-7U7L4NMD.js";
|
|
62
|
-
import {
|
|
63
|
-
debug
|
|
64
|
-
} from "./chunk-STSX7GIX.js";
|
|
65
|
-
import {
|
|
66
|
-
BunShell,
|
|
67
|
-
getCwd,
|
|
68
|
-
getMessagesPath,
|
|
69
|
-
getNextAvailableLogSidechainNumber,
|
|
70
|
-
logError,
|
|
71
|
-
overwriteLog,
|
|
72
|
-
readTaskOutput
|
|
73
|
-
} from "./chunk-YXYYDIMI.js";
|
|
74
|
-
import {
|
|
75
|
-
formatDuration,
|
|
76
|
-
formatNumber
|
|
77
|
-
} from "./chunk-EZXMVTDU.js";
|
|
78
|
-
|
|
79
|
-
// src/tools/index.ts
|
|
80
|
-
import { memoize as memoize2 } from "lodash-es";
|
|
81
|
-
|
|
82
|
-
// src/tools/ai/AskExpertModelTool/AskExpertModelTool.tsx
|
|
83
|
-
import * as React from "react";
|
|
84
|
-
import { Box, Text } from "ink";
|
|
85
|
-
import { z } from "zod";
|
|
86
|
-
|
|
87
|
-
// src/utils/session/expertChatStorage.ts
|
|
88
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
89
|
-
import { join } from "path";
|
|
90
|
-
import { homedir } from "os";
|
|
91
|
-
import { randomUUID } from "crypto";
|
|
92
|
-
function getExpertChatDirectory() {
|
|
93
|
-
const configDir = process.env.KODE_CONFIG_DIR ?? process.env.ANYKODE_CONFIG_DIR ?? join(homedir(), ".kode");
|
|
94
|
-
const expertChatDir = join(configDir, "expert-chats");
|
|
95
|
-
if (!existsSync(expertChatDir)) {
|
|
96
|
-
mkdirSync(expertChatDir, { recursive: true });
|
|
97
|
-
}
|
|
98
|
-
return expertChatDir;
|
|
99
|
-
}
|
|
100
|
-
function getSessionFilePath(sessionId) {
|
|
101
|
-
return join(getExpertChatDirectory(), `${sessionId}.json`);
|
|
102
|
-
}
|
|
103
|
-
function createExpertChatSession(expertModel) {
|
|
104
|
-
const sessionId = randomUUID().slice(0, 5);
|
|
105
|
-
const session = {
|
|
106
|
-
sessionId,
|
|
107
|
-
expertModel,
|
|
108
|
-
messages: [],
|
|
109
|
-
createdAt: Date.now(),
|
|
110
|
-
lastUpdated: Date.now()
|
|
111
|
-
};
|
|
112
|
-
saveExpertChatSession(session);
|
|
113
|
-
return session;
|
|
114
|
-
}
|
|
115
|
-
function loadExpertChatSession(sessionId) {
|
|
116
|
-
const filePath = getSessionFilePath(sessionId);
|
|
117
|
-
if (!existsSync(filePath)) {
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
try {
|
|
121
|
-
const content = readFileSync(filePath, "utf-8");
|
|
122
|
-
return JSON.parse(content);
|
|
123
|
-
} catch (error) {
|
|
124
|
-
logError(error);
|
|
125
|
-
debug.warn("EXPERT_CHAT_SESSION_LOAD_FAILED", {
|
|
126
|
-
sessionId,
|
|
127
|
-
error: error instanceof Error ? error.message : String(error)
|
|
128
|
-
});
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function saveExpertChatSession(session) {
|
|
133
|
-
const filePath = getSessionFilePath(session.sessionId);
|
|
134
|
-
try {
|
|
135
|
-
session.lastUpdated = Date.now();
|
|
136
|
-
writeFileSync(filePath, JSON.stringify(session, null, 2), "utf-8");
|
|
137
|
-
} catch (error) {
|
|
138
|
-
logError(error);
|
|
139
|
-
debug.warn("EXPERT_CHAT_SESSION_SAVE_FAILED", {
|
|
140
|
-
sessionId: session.sessionId,
|
|
141
|
-
error: error instanceof Error ? error.message : String(error)
|
|
142
|
-
});
|
|
143
|
-
throw error;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function addMessageToSession(sessionId, role, content) {
|
|
147
|
-
const session = loadExpertChatSession(sessionId);
|
|
148
|
-
if (!session) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
session.messages.push({ role, content });
|
|
152
|
-
saveExpertChatSession(session);
|
|
153
|
-
return session;
|
|
154
|
-
}
|
|
155
|
-
function getSessionMessages(sessionId) {
|
|
156
|
-
const session = loadExpertChatSession(sessionId);
|
|
157
|
-
return session?.messages || [];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// src/tools/ai/AskExpertModelTool/AskExpertModelTool.tsx
|
|
161
|
-
var inputSchema = z.strictObject({
|
|
162
|
-
question: z.string().describe(
|
|
163
|
-
"COMPLETE SELF-CONTAINED QUESTION: Must include full background context, relevant details, and a clear independent question. The expert model will receive ONLY this content with no access to previous conversation or external context. Structure as: 1) Background/Context 2) Specific situation/problem 3) Clear question. Ensure the expert can fully understand and respond without needing additional information."
|
|
164
|
-
),
|
|
165
|
-
expert_model: z.string().describe(
|
|
166
|
-
"The expert model to use (e.g., gpt-5, claude-3-5-sonnet-20241022)"
|
|
167
|
-
),
|
|
168
|
-
chat_session_id: z.string().describe(
|
|
169
|
-
'Chat session ID: use "new" for new session or existing session ID'
|
|
170
|
-
)
|
|
171
|
-
});
|
|
172
|
-
var AskExpertModelTool = {
|
|
173
|
-
name: "AskExpertModel",
|
|
174
|
-
async description() {
|
|
175
|
-
return "Consult external AI models for expert opinions and analysis";
|
|
176
|
-
},
|
|
177
|
-
async prompt() {
|
|
178
|
-
return `Ask a question to a specific external AI model for expert analysis.
|
|
179
|
-
|
|
180
|
-
This tool allows you to consult different AI models for their unique perspectives and expertise.
|
|
181
|
-
|
|
182
|
-
CRITICAL REQUIREMENT FOR QUESTION PARAMETER:
|
|
183
|
-
The question MUST be completely self-contained and include:
|
|
184
|
-
1. FULL BACKGROUND CONTEXT - All relevant information the expert needs
|
|
185
|
-
2. SPECIFIC SITUATION - Clear description of the current scenario/problem
|
|
186
|
-
3. INDEPENDENT QUESTION - What exactly you want the expert to analyze/answer
|
|
187
|
-
|
|
188
|
-
The expert model receives ONLY your question content with NO access to:
|
|
189
|
-
- Previous conversation history (unless using existing session)
|
|
190
|
-
- Current codebase or file context
|
|
191
|
-
- User's current task or project details
|
|
192
|
-
|
|
193
|
-
IMPORTANT: This tool is for asking questions to models, not for task execution.
|
|
194
|
-
- Use when you need a specific model's opinion or analysis
|
|
195
|
-
- Use when you want to compare different models' responses
|
|
196
|
-
- Use the @ask-[model] format when available
|
|
197
|
-
|
|
198
|
-
The expert_model parameter accepts:
|
|
199
|
-
- OpenAI: gpt-4, gpt-5, o1-preview
|
|
200
|
-
- Messages API: claude-3-5-sonnet, claude-3-opus
|
|
201
|
-
- Others: kimi, gemini-pro, mixtral
|
|
202
|
-
|
|
203
|
-
Example of well-structured question:
|
|
204
|
-
"Background: I'm working on a React TypeScript application with performance issues. The app renders a large list of 10,000 items using a simple map() function, causing UI freezing.
|
|
205
|
-
|
|
206
|
-
Current situation: Users report 3-5 second delays when scrolling through the list. The component re-renders the entire list on every state change.
|
|
207
|
-
|
|
208
|
-
Question: What are the most effective React optimization techniques for handling large lists, and how should I prioritize implementing virtualization vs memoization vs other approaches?"`;
|
|
209
|
-
},
|
|
210
|
-
isReadOnly() {
|
|
211
|
-
return true;
|
|
212
|
-
},
|
|
213
|
-
isConcurrencySafe() {
|
|
214
|
-
return true;
|
|
215
|
-
},
|
|
216
|
-
inputSchema,
|
|
217
|
-
userFacingName() {
|
|
218
|
-
return "AskExpertModel";
|
|
219
|
-
},
|
|
220
|
-
async isEnabled() {
|
|
221
|
-
return true;
|
|
222
|
-
},
|
|
223
|
-
needsPermissions() {
|
|
224
|
-
return false;
|
|
225
|
-
},
|
|
226
|
-
async validateInput({ question, expert_model, chat_session_id }, context) {
|
|
227
|
-
if (!question.trim()) {
|
|
228
|
-
return { result: false, message: "Question cannot be empty" };
|
|
229
|
-
}
|
|
230
|
-
if (!expert_model.trim()) {
|
|
231
|
-
return { result: false, message: "Expert model must be specified" };
|
|
232
|
-
}
|
|
233
|
-
if (!chat_session_id.trim()) {
|
|
234
|
-
return {
|
|
235
|
-
result: false,
|
|
236
|
-
message: 'Chat session ID must be specified (use "new" for new session)'
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
try {
|
|
240
|
-
const modelManager = getModelManager();
|
|
241
|
-
let currentModel;
|
|
242
|
-
if (context?.agentId && context?.options?.model) {
|
|
243
|
-
currentModel = context.options.model;
|
|
244
|
-
} else {
|
|
245
|
-
currentModel = modelManager.getModelName("main") || "";
|
|
246
|
-
}
|
|
247
|
-
const normalizedExpert = expert_model.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
248
|
-
const normalizedCurrent = currentModel.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
249
|
-
if (normalizedExpert === normalizedCurrent) {
|
|
250
|
-
return {
|
|
251
|
-
result: false,
|
|
252
|
-
message: `You are already running as ${currentModel}. Consulting the same model would be redundant. Please choose a different model or handle the task directly.`
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
} catch (e) {
|
|
256
|
-
debug.error("AskExpertModel", {
|
|
257
|
-
message: "Could not determine current model",
|
|
258
|
-
error: e
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
try {
|
|
262
|
-
const modelManager = getModelManager();
|
|
263
|
-
const modelResolution = modelManager.resolveModelWithInfo(expert_model);
|
|
264
|
-
if (!modelResolution.success) {
|
|
265
|
-
const availableModels = modelManager.getAllAvailableModelNames();
|
|
266
|
-
if (availableModels.length > 0) {
|
|
267
|
-
return {
|
|
268
|
-
result: false,
|
|
269
|
-
message: `Model '${expert_model}' is not configured. Available models: ${availableModels.join(", ")}. Check if any available model closely matches the user's request (e.g., 'kimi' matches 'kimi-k2-0711-preview'). If there's a strong match, auto retry using the correct model name. If no close match exists, inform the user that '${expert_model}' needs to be configured using /model command.`
|
|
270
|
-
};
|
|
271
|
-
} else {
|
|
272
|
-
return {
|
|
273
|
-
result: false,
|
|
274
|
-
message: `Model '${expert_model}' not found and no models are currently configured in the system. Inform the user that models need to be configured first using the /model command.`
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
} catch (error) {
|
|
279
|
-
logError(error);
|
|
280
|
-
return {
|
|
281
|
-
result: false,
|
|
282
|
-
message: `Failed to validate expert model '${expert_model}'. Please check your model configuration.`
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
return { result: true };
|
|
286
|
-
},
|
|
287
|
-
renderToolUseMessage({ question, expert_model, chat_session_id }, { verbose }) {
|
|
288
|
-
if (!question || !expert_model) return null;
|
|
289
|
-
const isNewSession = chat_session_id === "new";
|
|
290
|
-
const sessionDisplay = isNewSession ? "new session" : `session ${chat_session_id.substring(0, 5)}...`;
|
|
291
|
-
const theme = getTheme();
|
|
292
|
-
if (verbose) {
|
|
293
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "yellow" }, expert_model), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, sessionDisplay), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.text }, question.length > 300 ? question.substring(0, 300) + "..." : question)));
|
|
294
|
-
}
|
|
295
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "yellow" }, expert_model, " "), /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, dimColor: true }, "(", sessionDisplay, ")"));
|
|
296
|
-
},
|
|
297
|
-
renderToolResultMessage(content) {
|
|
298
|
-
const verbose = true;
|
|
299
|
-
const theme = getTheme();
|
|
300
|
-
if (typeof content === "object" && content && "expertAnswer" in content) {
|
|
301
|
-
const expertResult = content;
|
|
302
|
-
const isError = expertResult.expertAnswer.startsWith("Error") || expertResult.expertAnswer.includes("failed");
|
|
303
|
-
const isInterrupted = expertResult.chatSessionId === "interrupted";
|
|
304
|
-
if (isInterrupted) {
|
|
305
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "Consultation interrupted"));
|
|
306
|
-
}
|
|
307
|
-
const answerText = verbose ? expertResult.expertAnswer.trim() : expertResult.expertAnswer.length > 500 ? expertResult.expertAnswer.substring(0, 500) + "..." : expertResult.expertAnswer.trim();
|
|
308
|
-
if (isError) {
|
|
309
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, answerText));
|
|
310
|
-
}
|
|
311
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: theme.text }, "Response from ", expertResult.expertModelName, ":"), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.text }, applyMarkdown(answerText))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText, dimColor: true }, "Session: ", expertResult.chatSessionId.substring(0, 8))));
|
|
312
|
-
}
|
|
313
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, { color: theme.secondaryText }, "Consultation completed"));
|
|
314
|
-
},
|
|
315
|
-
renderResultForAssistant(output) {
|
|
316
|
-
return `[Expert consultation completed]
|
|
317
|
-
Expert Model: ${output.expertModelName}
|
|
318
|
-
Session ID: ${output.chatSessionId}
|
|
319
|
-
To continue this conversation with context preservation, use this Session ID in your next AskExpertModel call to maintain the full conversation history and context.
|
|
320
|
-
|
|
321
|
-
${output.expertAnswer}`;
|
|
322
|
-
},
|
|
323
|
-
renderToolUseRejectedMessage() {
|
|
324
|
-
return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
|
|
325
|
-
},
|
|
326
|
-
async *call({ question, expert_model, chat_session_id }, { abortController, readFileTimestamps }) {
|
|
327
|
-
const expertModel = expert_model;
|
|
328
|
-
let sessionId;
|
|
329
|
-
let isInterrupted = false;
|
|
330
|
-
const abortListener = () => {
|
|
331
|
-
isInterrupted = true;
|
|
332
|
-
};
|
|
333
|
-
abortController.signal.addEventListener("abort", abortListener);
|
|
334
|
-
try {
|
|
335
|
-
if (abortController.signal.aborted) {
|
|
336
|
-
return yield* this.handleInterrupt();
|
|
337
|
-
}
|
|
338
|
-
if (chat_session_id === "new") {
|
|
339
|
-
try {
|
|
340
|
-
const session = createExpertChatSession(expertModel);
|
|
341
|
-
sessionId = session.sessionId;
|
|
342
|
-
} catch (error) {
|
|
343
|
-
logError(error);
|
|
344
|
-
throw new Error("Failed to create new chat session");
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
sessionId = chat_session_id;
|
|
348
|
-
try {
|
|
349
|
-
const session = loadExpertChatSession(sessionId);
|
|
350
|
-
if (!session) {
|
|
351
|
-
const newSession = createExpertChatSession(expertModel);
|
|
352
|
-
sessionId = newSession.sessionId;
|
|
353
|
-
}
|
|
354
|
-
} catch (error) {
|
|
355
|
-
logError(error);
|
|
356
|
-
try {
|
|
357
|
-
const newSession = createExpertChatSession(expertModel);
|
|
358
|
-
sessionId = newSession.sessionId;
|
|
359
|
-
} catch (createError) {
|
|
360
|
-
logError(createError);
|
|
361
|
-
throw new Error("Unable to create or load chat session");
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
if (isInterrupted || abortController.signal.aborted) {
|
|
366
|
-
return yield* this.handleInterrupt();
|
|
367
|
-
}
|
|
368
|
-
let historyMessages;
|
|
369
|
-
try {
|
|
370
|
-
historyMessages = getSessionMessages(sessionId);
|
|
371
|
-
} catch (error) {
|
|
372
|
-
logError(error);
|
|
373
|
-
historyMessages = [];
|
|
374
|
-
}
|
|
375
|
-
const messages = [...historyMessages, { role: "user", content: question }];
|
|
376
|
-
let systemMessages;
|
|
377
|
-
try {
|
|
378
|
-
systemMessages = messages.map(
|
|
379
|
-
(msg) => msg.role === "user" ? createUserMessage(msg.content) : createAssistantMessage(msg.content)
|
|
380
|
-
);
|
|
381
|
-
} catch (error) {
|
|
382
|
-
logError(error);
|
|
383
|
-
throw new Error("Failed to prepare conversation messages");
|
|
384
|
-
}
|
|
385
|
-
if (isInterrupted || abortController.signal.aborted) {
|
|
386
|
-
return yield* this.handleInterrupt();
|
|
387
|
-
}
|
|
388
|
-
yield {
|
|
389
|
-
type: "progress",
|
|
390
|
-
content: createAssistantMessage(
|
|
391
|
-
`Connecting to ${expertModel}... (timeout: 5 minutes)`
|
|
392
|
-
)
|
|
393
|
-
};
|
|
394
|
-
let response;
|
|
395
|
-
try {
|
|
396
|
-
const modelManager = getModelManager();
|
|
397
|
-
const modelResolution = modelManager.resolveModelWithInfo(expertModel);
|
|
398
|
-
debug.api("EXPERT_MODEL_RESOLUTION", {
|
|
399
|
-
requestedModel: expertModel,
|
|
400
|
-
success: modelResolution.success,
|
|
401
|
-
profileName: modelResolution.profile?.name,
|
|
402
|
-
profileModelName: modelResolution.profile?.modelName,
|
|
403
|
-
provider: modelResolution.profile?.provider,
|
|
404
|
-
isActive: modelResolution.profile?.isActive,
|
|
405
|
-
error: modelResolution.error
|
|
406
|
-
});
|
|
407
|
-
const timeoutMs = 3e5;
|
|
408
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
409
|
-
setTimeout(() => {
|
|
410
|
-
reject(
|
|
411
|
-
new Error(
|
|
412
|
-
`Expert model query timed out after ${timeoutMs / 1e3}s`
|
|
413
|
-
)
|
|
414
|
-
);
|
|
415
|
-
}, timeoutMs);
|
|
416
|
-
});
|
|
417
|
-
response = await Promise.race([
|
|
418
|
-
queryLLM(
|
|
419
|
-
systemMessages,
|
|
420
|
-
[],
|
|
421
|
-
0,
|
|
422
|
-
[],
|
|
423
|
-
abortController.signal,
|
|
424
|
-
{
|
|
425
|
-
safeMode: false,
|
|
426
|
-
model: expertModel,
|
|
427
|
-
prependCLISysprompt: false
|
|
428
|
-
}
|
|
429
|
-
),
|
|
430
|
-
timeoutPromise
|
|
431
|
-
]);
|
|
432
|
-
} catch (error) {
|
|
433
|
-
logError(error);
|
|
434
|
-
if (error.name === "AbortError" || abortController.signal?.aborted || isInterrupted) {
|
|
435
|
-
return yield* this.handleInterrupt();
|
|
436
|
-
}
|
|
437
|
-
if (error.message?.includes("timed out")) {
|
|
438
|
-
throw new Error(
|
|
439
|
-
`Expert model '${expertModel}' timed out after 5 minutes.
|
|
440
|
-
|
|
441
|
-
Suggestions:
|
|
442
|
-
- The model might be experiencing high load
|
|
443
|
-
- Try a different model or retry later
|
|
444
|
-
- Consider breaking down your question into smaller parts`
|
|
445
|
-
);
|
|
446
|
-
}
|
|
447
|
-
if (error.message?.includes("rate limit")) {
|
|
448
|
-
throw new Error(
|
|
449
|
-
`Rate limit exceeded for ${expertModel}.
|
|
450
|
-
|
|
451
|
-
Please wait a moment and try again, or use a different model.`
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
if (error.message?.includes("invalid api key")) {
|
|
455
|
-
throw new Error(
|
|
456
|
-
`Invalid API key for ${expertModel}.
|
|
457
|
-
|
|
458
|
-
Please check your model configuration with /model command.`
|
|
459
|
-
);
|
|
460
|
-
}
|
|
461
|
-
if (error.message?.includes("model not found") || error.message?.includes("Failed to resolve model")) {
|
|
462
|
-
try {
|
|
463
|
-
const modelManager = getModelManager();
|
|
464
|
-
const availableModels = modelManager.getAllAvailableModelNames();
|
|
465
|
-
if (availableModels.length > 0) {
|
|
466
|
-
throw new Error(
|
|
467
|
-
`Model '${expertModel}' is not configured. Available models: ${availableModels.join(", ")}. Check if any available model closely matches the user's request (e.g., 'kimi' matches 'kimi-k2-0711-preview'). If there's a strong match, auto retry using the correct model name. If no close match exists, inform the user that '${expertModel}' needs to be configured using /model command.`
|
|
468
|
-
);
|
|
469
|
-
} else {
|
|
470
|
-
throw new Error(
|
|
471
|
-
`Model '${expertModel}' not found and no models are currently configured in the system. Inform the user that models need to be configured first using the /model command.`
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
} catch (modelError) {
|
|
475
|
-
throw new Error(
|
|
476
|
-
`Model '${expertModel}' not found. Please check model configuration or inform user about the issue.`
|
|
477
|
-
);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
throw new Error(
|
|
481
|
-
`Expert model query failed: ${error.message || "Unknown error"}`
|
|
482
|
-
);
|
|
483
|
-
}
|
|
484
|
-
let expertAnswer;
|
|
485
|
-
try {
|
|
486
|
-
if (!response?.message?.content) {
|
|
487
|
-
throw new Error("No content in expert response");
|
|
488
|
-
}
|
|
489
|
-
expertAnswer = response.message.content.filter((block) => block.type === "text").map((block) => block.text).join("\n");
|
|
490
|
-
if (!expertAnswer.trim()) {
|
|
491
|
-
throw new Error("Expert response was empty");
|
|
492
|
-
}
|
|
493
|
-
} catch (error) {
|
|
494
|
-
logError(error);
|
|
495
|
-
throw new Error("Failed to process expert response");
|
|
496
|
-
}
|
|
497
|
-
try {
|
|
498
|
-
addMessageToSession(sessionId, "user", question);
|
|
499
|
-
addMessageToSession(sessionId, "assistant", expertAnswer);
|
|
500
|
-
} catch (error) {
|
|
501
|
-
logError(error);
|
|
502
|
-
}
|
|
503
|
-
const result = {
|
|
504
|
-
chatSessionId: sessionId,
|
|
505
|
-
expertModelName: expertModel,
|
|
506
|
-
expertAnswer
|
|
507
|
-
};
|
|
508
|
-
yield {
|
|
509
|
-
type: "result",
|
|
510
|
-
data: result,
|
|
511
|
-
resultForAssistant: this.renderResultForAssistant(result)
|
|
512
|
-
};
|
|
513
|
-
} catch (error) {
|
|
514
|
-
if (error.name === "AbortError" || abortController.signal?.aborted || isInterrupted) {
|
|
515
|
-
return yield* this.handleInterrupt();
|
|
516
|
-
}
|
|
517
|
-
logError(error);
|
|
518
|
-
const errorSessionId = sessionId || "error-session";
|
|
519
|
-
const errorMessage = error.message || "Expert consultation failed with unknown error";
|
|
520
|
-
const result = {
|
|
521
|
-
chatSessionId: errorSessionId,
|
|
522
|
-
expertModelName: expertModel,
|
|
523
|
-
expertAnswer: `\u274C ${errorMessage}`
|
|
524
|
-
};
|
|
525
|
-
yield {
|
|
526
|
-
type: "result",
|
|
527
|
-
data: result,
|
|
528
|
-
resultForAssistant: this.renderResultForAssistant(result)
|
|
529
|
-
};
|
|
530
|
-
} finally {
|
|
531
|
-
abortController.signal.removeEventListener("abort", abortListener);
|
|
532
|
-
}
|
|
533
|
-
},
|
|
534
|
-
async *handleInterrupt() {
|
|
535
|
-
yield {
|
|
536
|
-
type: "result",
|
|
537
|
-
data: {
|
|
538
|
-
chatSessionId: "interrupted",
|
|
539
|
-
expertModelName: "cancelled",
|
|
540
|
-
expertAnswer: INTERRUPT_MESSAGE
|
|
541
|
-
},
|
|
542
|
-
resultForAssistant: INTERRUPT_MESSAGE
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
};
|
|
546
|
-
|
|
547
|
-
// src/tools/system/TaskOutputTool/TaskOutputTool.tsx
|
|
548
|
-
import { Box as Box2, Text as Text2 } from "ink";
|
|
549
|
-
import React2 from "react";
|
|
550
|
-
import { z as z2 } from "zod";
|
|
551
|
-
|
|
552
|
-
// src/utils/session/backgroundTasks.ts
|
|
553
|
-
var backgroundTasks = /* @__PURE__ */ new Map();
|
|
554
|
-
function getBackgroundAgentTaskSnapshot(agentId) {
|
|
555
|
-
const task = backgroundTasks.get(agentId);
|
|
556
|
-
if (!task) return void 0;
|
|
557
|
-
const { abortController: _abortController, done: _done, ...snapshot } = task;
|
|
558
|
-
return snapshot;
|
|
559
|
-
}
|
|
560
|
-
function upsertBackgroundAgentTask(task) {
|
|
561
|
-
backgroundTasks.set(task.agentId, task);
|
|
562
|
-
}
|
|
563
|
-
async function waitForBackgroundAgentTask(agentId, waitUpToMs, signal) {
|
|
564
|
-
const task = backgroundTasks.get(agentId);
|
|
565
|
-
if (!task) return void 0;
|
|
566
|
-
if (task.status !== "running") return task;
|
|
567
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
568
|
-
const timeoutId = setTimeout(() => {
|
|
569
|
-
reject(new Error("Request timed out"));
|
|
570
|
-
}, waitUpToMs);
|
|
571
|
-
timeoutId.unref?.();
|
|
572
|
-
});
|
|
573
|
-
const abortPromise = new Promise((_, reject) => {
|
|
574
|
-
if (signal.aborted) {
|
|
575
|
-
reject(new Error("Request aborted"));
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
const onAbort = () => reject(new Error("Request aborted"));
|
|
579
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
580
|
-
});
|
|
581
|
-
await Promise.race([task.done, timeoutPromise, abortPromise]);
|
|
582
|
-
return backgroundTasks.get(agentId);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// src/utils/tooling/toolOutputDisplay.ts
|
|
586
|
-
function isTruthyEnv(value) {
|
|
587
|
-
if (!value) return false;
|
|
588
|
-
return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
|
|
589
|
-
}
|
|
590
|
-
function isPackagedRuntime() {
|
|
591
|
-
if (isTruthyEnv(process.env.KODE_PACKAGED)) return true;
|
|
592
|
-
try {
|
|
593
|
-
const exec = (process.execPath || "").split(/[\\/]/).pop()?.toLowerCase();
|
|
594
|
-
if (!exec) return false;
|
|
595
|
-
if (exec === "bun" || exec === "bun.exe") return false;
|
|
596
|
-
if (exec === "node" || exec === "node.exe") return false;
|
|
597
|
-
return true;
|
|
598
|
-
} catch {
|
|
599
|
-
return false;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
function truncateTextForDisplay(text, options) {
|
|
603
|
-
const maxLines = options?.maxLines ?? 120;
|
|
604
|
-
const maxChars = options?.maxChars ?? 12e3;
|
|
605
|
-
const normalized = String(text ?? "");
|
|
606
|
-
const lines = normalized.split(/\r?\n/);
|
|
607
|
-
let workingLines = lines;
|
|
608
|
-
let omittedLines = 0;
|
|
609
|
-
if (maxLines > 0 && lines.length > maxLines) {
|
|
610
|
-
workingLines = lines.slice(0, maxLines);
|
|
611
|
-
omittedLines = lines.length - maxLines;
|
|
612
|
-
}
|
|
613
|
-
let workingText = workingLines.join("\n");
|
|
614
|
-
let omittedChars = 0;
|
|
615
|
-
if (maxChars > 0 && workingText.length > maxChars) {
|
|
616
|
-
omittedChars = workingText.length - maxChars;
|
|
617
|
-
workingText = workingText.slice(0, maxChars);
|
|
618
|
-
}
|
|
619
|
-
const truncated = omittedLines > 0 || omittedChars > 0;
|
|
620
|
-
if (!truncated) {
|
|
621
|
-
return {
|
|
622
|
-
text: workingText,
|
|
623
|
-
truncated: false,
|
|
624
|
-
omittedLines: 0,
|
|
625
|
-
omittedChars: 0
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
const suffixParts = [];
|
|
629
|
-
if (omittedLines > 0) {
|
|
630
|
-
suffixParts.push(`${omittedLines} lines`);
|
|
631
|
-
}
|
|
632
|
-
if (omittedChars > 0) {
|
|
633
|
-
suffixParts.push(`${omittedChars} chars`);
|
|
634
|
-
}
|
|
635
|
-
const suffix = `
|
|
636
|
-
|
|
637
|
-
... [truncated ${suffixParts.join(" \xB7 ")}] ...`;
|
|
638
|
-
return {
|
|
639
|
-
text: workingText + suffix,
|
|
640
|
-
truncated: true,
|
|
641
|
-
omittedLines,
|
|
642
|
-
omittedChars
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
function maybeTruncateVerboseToolOutput(text, options) {
|
|
646
|
-
const maxLinesEnv = Number(process.env.KODE_TOOL_OUTPUT_MAX_LINES ?? "");
|
|
647
|
-
const maxCharsEnv = Number(process.env.KODE_TOOL_OUTPUT_MAX_CHARS ?? "");
|
|
648
|
-
const envOverrides = {
|
|
649
|
-
maxLines: Number.isFinite(maxLinesEnv) && maxLinesEnv > 0 ? maxLinesEnv : void 0,
|
|
650
|
-
maxChars: Number.isFinite(maxCharsEnv) && maxCharsEnv > 0 ? maxCharsEnv : void 0
|
|
651
|
-
};
|
|
652
|
-
const effective = {
|
|
653
|
-
maxLines: envOverrides.maxLines ?? options?.maxLines,
|
|
654
|
-
maxChars: envOverrides.maxChars ?? options?.maxChars
|
|
655
|
-
};
|
|
656
|
-
const fullAllowed = isTruthyEnv(process.env.KODE_TOOL_OUTPUT_FULL);
|
|
657
|
-
if (!isPackagedRuntime() || fullAllowed) {
|
|
658
|
-
return { text: String(text ?? ""), truncated: false };
|
|
659
|
-
}
|
|
660
|
-
const result = truncateTextForDisplay(String(text ?? ""), effective);
|
|
661
|
-
return { text: result.text, truncated: result.truncated };
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// src/tools/system/TaskOutputTool/prompt.ts
|
|
665
|
-
var TOOL_NAME_FOR_PROMPT = "TaskOutput";
|
|
666
|
-
var DESCRIPTION = "Retrieves output from a running or completed task";
|
|
667
|
-
var PROMPT = `- Retrieves output from a running or completed task (background shell, agent, or remote session)
|
|
668
|
-
- Takes a task_id parameter identifying the task
|
|
669
|
-
- Returns the task output along with status information
|
|
670
|
-
- Use block=true (default) to wait for task completion
|
|
671
|
-
- Use block=false for non-blocking check of current status
|
|
672
|
-
- Task IDs can be found using the /tasks command
|
|
673
|
-
- Works with all task types: background shells, async agents, and remote sessions`;
|
|
674
|
-
|
|
675
|
-
// src/tools/system/TaskOutputTool/TaskOutputTool.tsx
|
|
676
|
-
var inputSchema2 = z2.strictObject({
|
|
677
|
-
task_id: z2.string().describe("The task ID to get output from"),
|
|
678
|
-
block: z2.boolean().optional().default(true).describe("Whether to wait for completion"),
|
|
679
|
-
timeout: z2.number().min(0).max(6e5).optional().default(3e4).describe("Max wait time in ms")
|
|
680
|
-
});
|
|
681
|
-
function normalizeTaskOutputInput(input) {
|
|
682
|
-
const task_id = typeof input.task_id === "string" && input.task_id || typeof input.agentId === "string" && String(input.agentId) || typeof input.bash_id === "string" && String(input.bash_id) || "";
|
|
683
|
-
const block = typeof input.block === "boolean" ? input.block : true;
|
|
684
|
-
const timeout = typeof input.timeout === "number" ? input.timeout : typeof input.wait_up_to === "number" ? Number(input.wait_up_to) * 1e3 : 3e4;
|
|
685
|
-
return { task_id, block, timeout };
|
|
686
|
-
}
|
|
687
|
-
function taskStatusFromBash(bg) {
|
|
688
|
-
if (!bg) return "failed";
|
|
689
|
-
if (bg.killed) return "killed";
|
|
690
|
-
if (bg.code === null) return "running";
|
|
691
|
-
return bg.code === 0 ? "completed" : "failed";
|
|
692
|
-
}
|
|
693
|
-
function buildTaskSummary(taskId) {
|
|
694
|
-
const bg = BunShell.getInstance().getBackgroundOutput(taskId);
|
|
695
|
-
if (bg) {
|
|
696
|
-
return {
|
|
697
|
-
task_id: taskId,
|
|
698
|
-
task_type: "local_bash",
|
|
699
|
-
status: taskStatusFromBash(bg),
|
|
700
|
-
description: bg.command,
|
|
701
|
-
output: readTaskOutput(taskId),
|
|
702
|
-
exitCode: bg.code
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
const agent = getBackgroundAgentTaskSnapshot(taskId);
|
|
706
|
-
if (agent) {
|
|
707
|
-
const output = readTaskOutput(taskId) || agent.resultText || "";
|
|
708
|
-
return {
|
|
709
|
-
task_id: taskId,
|
|
710
|
-
task_type: "local_agent",
|
|
711
|
-
status: agent.status,
|
|
712
|
-
description: agent.description,
|
|
713
|
-
output,
|
|
714
|
-
prompt: agent.prompt,
|
|
715
|
-
result: output,
|
|
716
|
-
error: agent.error
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
return null;
|
|
720
|
-
}
|
|
721
|
-
async function waitForBashTaskCompletion(args) {
|
|
722
|
-
const { taskId, timeoutMs, signal } = args;
|
|
723
|
-
const startedAt = Date.now();
|
|
724
|
-
while (Date.now() - startedAt < timeoutMs) {
|
|
725
|
-
if (signal.aborted) return null;
|
|
726
|
-
const summary = buildTaskSummary(taskId);
|
|
727
|
-
if (!summary) return null;
|
|
728
|
-
if (summary.status !== "running" && summary.status !== "pending")
|
|
729
|
-
return summary;
|
|
730
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
731
|
-
}
|
|
732
|
-
return buildTaskSummary(taskId);
|
|
733
|
-
}
|
|
734
|
-
var TaskOutputTool = {
|
|
735
|
-
name: TOOL_NAME_FOR_PROMPT,
|
|
736
|
-
async description() {
|
|
737
|
-
return DESCRIPTION;
|
|
738
|
-
},
|
|
739
|
-
userFacingName() {
|
|
740
|
-
return "Task Output";
|
|
741
|
-
},
|
|
742
|
-
inputSchema: inputSchema2,
|
|
743
|
-
isReadOnly() {
|
|
744
|
-
return true;
|
|
745
|
-
},
|
|
746
|
-
isConcurrencySafe() {
|
|
747
|
-
return true;
|
|
748
|
-
},
|
|
749
|
-
async isEnabled() {
|
|
750
|
-
return true;
|
|
751
|
-
},
|
|
752
|
-
needsPermissions() {
|
|
753
|
-
return false;
|
|
754
|
-
},
|
|
755
|
-
async prompt() {
|
|
756
|
-
return PROMPT;
|
|
757
|
-
},
|
|
758
|
-
renderToolUseMessage(input) {
|
|
759
|
-
const normalized = normalizeTaskOutputInput(input);
|
|
760
|
-
if (!normalized.block) return "non-blocking";
|
|
761
|
-
return "";
|
|
762
|
-
},
|
|
763
|
-
renderToolUseRejectedMessage() {
|
|
764
|
-
return null;
|
|
765
|
-
},
|
|
766
|
-
renderToolResultMessage(output, { verbose }) {
|
|
767
|
-
const theme = getTheme();
|
|
768
|
-
if (output.retrieval_status === "timeout" || output.retrieval_status === "not_ready") {
|
|
769
|
-
return /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { color: theme.secondaryText }, "Task is still running\u2026"));
|
|
770
|
-
}
|
|
771
|
-
if (!output.task) {
|
|
772
|
-
return /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { color: theme.secondaryText }, "No task output available"));
|
|
773
|
-
}
|
|
774
|
-
if (output.task.task_type === "local_agent") {
|
|
775
|
-
const lines = output.task.result ? output.task.result.split("\n").length : 0;
|
|
776
|
-
if (!verbose) {
|
|
777
|
-
return /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { color: theme.secondaryText }, "Read output (ctrl+o to expand)"));
|
|
778
|
-
}
|
|
779
|
-
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, null, output.task.description, " (", lines, " lines)"), output.task.prompt ? /* @__PURE__ */ React2.createElement(Box2, { paddingLeft: 2 }, /* @__PURE__ */ React2.createElement(Text2, { color: theme.secondaryText }, output.task.prompt)) : null, output.task.result ? /* @__PURE__ */ React2.createElement(Box2, { paddingLeft: 2, marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, maybeTruncateVerboseToolOutput(output.task.result, {
|
|
780
|
-
maxLines: 200,
|
|
781
|
-
maxChars: 4e4
|
|
782
|
-
}).text)) : null, output.task.error ? /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, paddingLeft: 2 }, /* @__PURE__ */ React2.createElement(Text2, { color: theme.error, bold: true }, "Error:"), /* @__PURE__ */ React2.createElement(Text2, { color: theme.error }, output.task.error)) : null);
|
|
783
|
-
}
|
|
784
|
-
const content = output.task.output?.trimEnd() ?? "";
|
|
785
|
-
if (!verbose) {
|
|
786
|
-
return /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { color: theme.secondaryText }, content.length > 0 ? "Read output (ctrl+o to expand)" : "(No content)"));
|
|
787
|
-
}
|
|
788
|
-
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, { color: theme.secondaryText }, output.task.description), content ? /* @__PURE__ */ React2.createElement(Box2, { paddingLeft: 2, marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, maybeTruncateVerboseToolOutput(content, {
|
|
789
|
-
maxLines: 200,
|
|
790
|
-
maxChars: 4e4
|
|
791
|
-
}).text)) : null);
|
|
792
|
-
},
|
|
793
|
-
renderResultForAssistant(output) {
|
|
794
|
-
const parts = [];
|
|
795
|
-
parts.push(
|
|
796
|
-
`<retrieval_status>${output.retrieval_status}</retrieval_status>`
|
|
797
|
-
);
|
|
798
|
-
if (output.task) {
|
|
799
|
-
parts.push(`<task_id>${output.task.task_id}</task_id>`);
|
|
800
|
-
parts.push(`<task_type>${output.task.task_type}</task_type>`);
|
|
801
|
-
parts.push(`<status>${output.task.status}</status>`);
|
|
802
|
-
if (output.task.exitCode !== void 0 && output.task.exitCode !== null) {
|
|
803
|
-
parts.push(`<exit_code>${output.task.exitCode}</exit_code>`);
|
|
804
|
-
}
|
|
805
|
-
if (output.task.output?.trim()) {
|
|
806
|
-
parts.push(`<output>
|
|
807
|
-
${output.task.output.trimEnd()}
|
|
808
|
-
</output>`);
|
|
809
|
-
}
|
|
810
|
-
if (output.task.error) {
|
|
811
|
-
parts.push(`<error>${output.task.error}</error>`);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
return parts.join("\n\n");
|
|
815
|
-
},
|
|
816
|
-
async validateInput(input) {
|
|
817
|
-
if (!input.task_id) {
|
|
818
|
-
return { result: false, message: "Task ID is required", errorCode: 1 };
|
|
819
|
-
}
|
|
820
|
-
const task = buildTaskSummary(input.task_id);
|
|
821
|
-
if (!task) {
|
|
822
|
-
return {
|
|
823
|
-
result: false,
|
|
824
|
-
message: `No task found with ID: ${input.task_id}`,
|
|
825
|
-
errorCode: 2
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
return { result: true };
|
|
829
|
-
},
|
|
830
|
-
async *call(input, context) {
|
|
831
|
-
const normalized = normalizeTaskOutputInput(input);
|
|
832
|
-
const taskId = normalized.task_id;
|
|
833
|
-
const block = normalized.block;
|
|
834
|
-
const timeoutMs = normalized.timeout;
|
|
835
|
-
const initial = buildTaskSummary(taskId);
|
|
836
|
-
if (!initial) {
|
|
837
|
-
throw new Error(`No task found with ID: ${taskId}`);
|
|
838
|
-
}
|
|
839
|
-
if (!block) {
|
|
840
|
-
const isDone = initial.status !== "running" && initial.status !== "pending";
|
|
841
|
-
const out2 = {
|
|
842
|
-
retrieval_status: isDone ? "success" : "not_ready",
|
|
843
|
-
task: initial
|
|
844
|
-
};
|
|
845
|
-
yield {
|
|
846
|
-
type: "result",
|
|
847
|
-
data: out2,
|
|
848
|
-
resultForAssistant: this.renderResultForAssistant(out2)
|
|
849
|
-
};
|
|
850
|
-
return;
|
|
851
|
-
}
|
|
852
|
-
yield {
|
|
853
|
-
type: "progress",
|
|
854
|
-
content: createAssistantMessage(
|
|
855
|
-
`<tool-progress>${initial.description ? ` ${initial.description}
|
|
856
|
-
` : ""} Waiting for task (esc to give additional instructions)</tool-progress>`
|
|
857
|
-
)
|
|
858
|
-
};
|
|
859
|
-
let finalTask = null;
|
|
860
|
-
if (initial.task_type === "local_agent") {
|
|
861
|
-
try {
|
|
862
|
-
const task = await waitForBackgroundAgentTask(
|
|
863
|
-
taskId,
|
|
864
|
-
timeoutMs,
|
|
865
|
-
context.abortController.signal
|
|
866
|
-
);
|
|
867
|
-
finalTask = task ? buildTaskSummary(taskId) : null;
|
|
868
|
-
} catch {
|
|
869
|
-
finalTask = buildTaskSummary(taskId);
|
|
870
|
-
}
|
|
871
|
-
} else {
|
|
872
|
-
finalTask = await waitForBashTaskCompletion({
|
|
873
|
-
taskId,
|
|
874
|
-
timeoutMs,
|
|
875
|
-
signal: context.abortController.signal
|
|
876
|
-
});
|
|
877
|
-
}
|
|
878
|
-
if (!finalTask) {
|
|
879
|
-
const out2 = { retrieval_status: "timeout", task: null };
|
|
880
|
-
yield {
|
|
881
|
-
type: "result",
|
|
882
|
-
data: out2,
|
|
883
|
-
resultForAssistant: this.renderResultForAssistant(out2)
|
|
884
|
-
};
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
if (finalTask.status === "running" || finalTask.status === "pending") {
|
|
888
|
-
const out2 = { retrieval_status: "timeout", task: finalTask };
|
|
889
|
-
yield {
|
|
890
|
-
type: "result",
|
|
891
|
-
data: out2,
|
|
892
|
-
resultForAssistant: this.renderResultForAssistant(out2)
|
|
893
|
-
};
|
|
894
|
-
return;
|
|
895
|
-
}
|
|
896
|
-
const out = { retrieval_status: "success", task: finalTask };
|
|
897
|
-
yield {
|
|
898
|
-
type: "result",
|
|
899
|
-
data: out,
|
|
900
|
-
resultForAssistant: this.renderResultForAssistant(out)
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
};
|
|
904
|
-
|
|
905
|
-
// src/tools/mcp/ListMcpResourcesTool/ListMcpResourcesTool.tsx
|
|
906
|
-
import { Box as Box3, Text as Text3 } from "ink";
|
|
907
|
-
import React3 from "react";
|
|
908
|
-
import { z as z3 } from "zod";
|
|
909
|
-
import { ListResourcesResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
910
|
-
|
|
911
|
-
// src/tools/mcp/ListMcpResourcesTool/prompt.ts
|
|
912
|
-
var TOOL_NAME = "ListMcpResourcesTool";
|
|
913
|
-
var DESCRIPTION2 = `Lists available resources from configured MCP servers.
|
|
914
|
-
Each resource object includes a 'server' field indicating which server it's from.
|
|
915
|
-
|
|
916
|
-
Usage examples:
|
|
917
|
-
- List all resources from all servers: \`listMcpResources\`
|
|
918
|
-
- List resources from a specific server: \`listMcpResources({ server: "myserver" })\``;
|
|
919
|
-
var PROMPT2 = `List available resources from configured MCP servers.
|
|
920
|
-
Each returned resource will include all standard MCP resource fields plus a 'server' field
|
|
921
|
-
indicating which server the resource belongs to.
|
|
922
|
-
|
|
923
|
-
Parameters:
|
|
924
|
-
- server (optional): The name of a specific MCP server to get resources from. If not provided,
|
|
925
|
-
resources from all servers will be returned.`;
|
|
926
|
-
|
|
927
|
-
// src/tools/mcp/ListMcpResourcesTool/ListMcpResourcesTool.tsx
|
|
928
|
-
var inputSchema3 = z3.strictObject({
|
|
929
|
-
server: z3.string().optional().describe("Optional server name to filter resources by")
|
|
930
|
-
});
|
|
931
|
-
var ListMcpResourcesTool = {
|
|
932
|
-
name: TOOL_NAME,
|
|
933
|
-
async description() {
|
|
934
|
-
return DESCRIPTION2;
|
|
935
|
-
},
|
|
936
|
-
async prompt() {
|
|
937
|
-
return PROMPT2;
|
|
938
|
-
},
|
|
939
|
-
inputSchema: inputSchema3,
|
|
940
|
-
userFacingName() {
|
|
941
|
-
return "listMcpResources";
|
|
942
|
-
},
|
|
943
|
-
async isEnabled() {
|
|
944
|
-
return true;
|
|
945
|
-
},
|
|
946
|
-
isReadOnly() {
|
|
947
|
-
return true;
|
|
948
|
-
},
|
|
949
|
-
isConcurrencySafe() {
|
|
950
|
-
return true;
|
|
951
|
-
},
|
|
952
|
-
needsPermissions() {
|
|
953
|
-
return false;
|
|
954
|
-
},
|
|
955
|
-
async validateInput({ server }, context) {
|
|
956
|
-
if (!server) return { result: true };
|
|
957
|
-
const clients = context?.options?.mcpClients ?? await getClients();
|
|
958
|
-
const found = clients.some((c) => c.name === server);
|
|
959
|
-
if (!found) {
|
|
960
|
-
return {
|
|
961
|
-
result: false,
|
|
962
|
-
message: `Server "${server}" not found. Available servers: ${clients.map((c) => c.name).join(", ")}`,
|
|
963
|
-
errorCode: 1
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
return { result: true };
|
|
967
|
-
},
|
|
968
|
-
renderToolUseMessage({ server }) {
|
|
969
|
-
return server ? `List MCP resources from server "${server}"` : "List all MCP resources";
|
|
970
|
-
},
|
|
971
|
-
renderToolUseRejectedMessage() {
|
|
972
|
-
return /* @__PURE__ */ React3.createElement(FallbackToolUseRejectedMessage, null);
|
|
973
|
-
},
|
|
974
|
-
renderToolResultMessage(output) {
|
|
975
|
-
return /* @__PURE__ */ React3.createElement(Box3, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React3.createElement(Text3, { bold: true }, output.length), /* @__PURE__ */ React3.createElement(Text3, null, " resources")), /* @__PURE__ */ React3.createElement(Cost, { costUSD: 0, durationMs: 0, debug: false }));
|
|
976
|
-
},
|
|
977
|
-
renderResultForAssistant(output) {
|
|
978
|
-
return JSON.stringify(output);
|
|
979
|
-
},
|
|
980
|
-
async *call({ server }, context) {
|
|
981
|
-
const clients = context.options?.mcpClients ?? await getClients();
|
|
982
|
-
const selected = server ? clients.filter((c) => c.name === server) : clients;
|
|
983
|
-
if (server && selected.length === 0) {
|
|
984
|
-
throw new Error(
|
|
985
|
-
`Server "${server}" not found. Available servers: ${clients.map((c) => c.name).join(", ")}`
|
|
986
|
-
);
|
|
987
|
-
}
|
|
988
|
-
const resources = [];
|
|
989
|
-
for (const wrapped of selected) {
|
|
990
|
-
if (wrapped.type !== "connected") continue;
|
|
991
|
-
try {
|
|
992
|
-
let capabilities = wrapped.capabilities ?? null;
|
|
993
|
-
if (!capabilities) {
|
|
994
|
-
try {
|
|
995
|
-
capabilities = wrapped.client.getServerCapabilities();
|
|
996
|
-
} catch {
|
|
997
|
-
capabilities = null;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
if (!capabilities?.resources) continue;
|
|
1001
|
-
const result = await wrapped.client.request(
|
|
1002
|
-
{ method: "resources/list" },
|
|
1003
|
-
ListResourcesResultSchema
|
|
1004
|
-
);
|
|
1005
|
-
if (!result.resources) continue;
|
|
1006
|
-
resources.push(
|
|
1007
|
-
...result.resources.map((r) => ({
|
|
1008
|
-
...r,
|
|
1009
|
-
server: wrapped.name
|
|
1010
|
-
}))
|
|
1011
|
-
);
|
|
1012
|
-
} catch {
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
yield {
|
|
1016
|
-
type: "result",
|
|
1017
|
-
data: resources,
|
|
1018
|
-
resultForAssistant: this.renderResultForAssistant(resources)
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
};
|
|
1022
|
-
|
|
1023
|
-
// src/tools/search/LspTool/LspTool.tsx
|
|
1024
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "fs";
|
|
1025
|
-
import { Box as Box4, Text as Text4 } from "ink";
|
|
1026
|
-
import { createRequire } from "node:module";
|
|
1027
|
-
import { extname, join as join2, relative } from "path";
|
|
1028
|
-
import React4 from "react";
|
|
1029
|
-
import { pathToFileURL } from "url";
|
|
1030
|
-
import { z as z4 } from "zod";
|
|
1031
|
-
|
|
1032
|
-
// src/tools/search/LspTool/prompt.ts
|
|
1033
|
-
var TOOL_NAME_FOR_PROMPT2 = "LSP";
|
|
1034
|
-
var PROMPT3 = `Interact with Language Server Protocol (LSP) servers to get code intelligence features.
|
|
1035
|
-
|
|
1036
|
-
Supported operations:
|
|
1037
|
-
- goToDefinition: Find where a symbol is defined
|
|
1038
|
-
- findReferences: Find all references to a symbol
|
|
1039
|
-
- hover: Get hover information (documentation, type info) for a symbol
|
|
1040
|
-
- documentSymbol: Get all symbols (functions, classes, variables) in a document
|
|
1041
|
-
- workspaceSymbol: Search for symbols across the entire workspace
|
|
1042
|
-
- goToImplementation: Find implementations of an interface or abstract method
|
|
1043
|
-
- prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)
|
|
1044
|
-
- incomingCalls: Find all functions/methods that call the function at a position
|
|
1045
|
-
- outgoingCalls: Find all functions/methods called by the function at a position
|
|
1046
|
-
|
|
1047
|
-
All operations require:
|
|
1048
|
-
- filePath: The file to operate on
|
|
1049
|
-
- line: The line number (1-based, as shown in editors)
|
|
1050
|
-
- character: The character offset (1-based, as shown in editors)
|
|
1051
|
-
|
|
1052
|
-
Note: LSP servers must be configured for the file type. If no server is available, an error will be returned.`;
|
|
1053
|
-
var DESCRIPTION3 = PROMPT3;
|
|
1054
|
-
|
|
1055
|
-
// src/tools/search/LspTool/LspTool.tsx
|
|
1056
|
-
var inputSchema4 = z4.strictObject({
|
|
1057
|
-
operation: z4.enum([
|
|
1058
|
-
"goToDefinition",
|
|
1059
|
-
"findReferences",
|
|
1060
|
-
"hover",
|
|
1061
|
-
"documentSymbol",
|
|
1062
|
-
"workspaceSymbol",
|
|
1063
|
-
"goToImplementation",
|
|
1064
|
-
"prepareCallHierarchy",
|
|
1065
|
-
"incomingCalls",
|
|
1066
|
-
"outgoingCalls"
|
|
1067
|
-
]).describe("The LSP operation to perform"),
|
|
1068
|
-
filePath: z4.string().describe("The absolute or relative path to the file"),
|
|
1069
|
-
line: z4.number().int().positive().describe("The line number (1-based, as shown in editors)"),
|
|
1070
|
-
character: z4.number().int().positive().describe("The character offset (1-based, as shown in editors)")
|
|
1071
|
-
});
|
|
1072
|
-
var outputSchema = z4.object({
|
|
1073
|
-
operation: z4.enum([
|
|
1074
|
-
"goToDefinition",
|
|
1075
|
-
"findReferences",
|
|
1076
|
-
"hover",
|
|
1077
|
-
"documentSymbol",
|
|
1078
|
-
"workspaceSymbol",
|
|
1079
|
-
"goToImplementation",
|
|
1080
|
-
"prepareCallHierarchy",
|
|
1081
|
-
"incomingCalls",
|
|
1082
|
-
"outgoingCalls"
|
|
1083
|
-
]).describe("The LSP operation that was performed"),
|
|
1084
|
-
result: z4.string().describe("The formatted result of the LSP operation"),
|
|
1085
|
-
filePath: z4.string().describe("The file path the operation was performed on"),
|
|
1086
|
-
resultCount: z4.number().int().nonnegative().optional().describe("Number of results (definitions, references, symbols)"),
|
|
1087
|
-
fileCount: z4.number().int().nonnegative().optional().describe("Number of files containing results")
|
|
1088
|
-
});
|
|
1089
|
-
var OPERATION_LABELS = {
|
|
1090
|
-
goToDefinition: { singular: "definition", plural: "definitions" },
|
|
1091
|
-
findReferences: { singular: "reference", plural: "references" },
|
|
1092
|
-
documentSymbol: { singular: "symbol", plural: "symbols" },
|
|
1093
|
-
workspaceSymbol: { singular: "symbol", plural: "symbols" },
|
|
1094
|
-
hover: { singular: "hover info", plural: "hover info", special: "available" },
|
|
1095
|
-
goToImplementation: { singular: "implementation", plural: "implementations" },
|
|
1096
|
-
prepareCallHierarchy: { singular: "call item", plural: "call items" },
|
|
1097
|
-
incomingCalls: { singular: "caller", plural: "callers" },
|
|
1098
|
-
outgoingCalls: { singular: "callee", plural: "callees" }
|
|
1099
|
-
};
|
|
1100
|
-
function extractSymbolAtPosition(lines, zeroBasedLine, zeroBasedCharacter) {
|
|
1101
|
-
try {
|
|
1102
|
-
if (zeroBasedLine < 0 || zeroBasedLine >= lines.length) return null;
|
|
1103
|
-
const line = lines[zeroBasedLine];
|
|
1104
|
-
if (zeroBasedCharacter < 0 || zeroBasedCharacter >= line.length) return null;
|
|
1105
|
-
const tokenRe = /[\w$'!]+|[+\-*/%&|^~<>=]+/g;
|
|
1106
|
-
let match;
|
|
1107
|
-
while ((match = tokenRe.exec(line)) !== null) {
|
|
1108
|
-
const start = match.index;
|
|
1109
|
-
const end = start + match[0].length;
|
|
1110
|
-
if (zeroBasedCharacter >= start && zeroBasedCharacter < end) {
|
|
1111
|
-
const token = match[0];
|
|
1112
|
-
return token.length > 30 ? `${token.slice(0, 27)}...` : token;
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
return null;
|
|
1116
|
-
} catch {
|
|
1117
|
-
return null;
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
function toProjectRelativeIfPossible(filePath) {
|
|
1121
|
-
const cwd = getCwd();
|
|
1122
|
-
try {
|
|
1123
|
-
const rel = relative(cwd, filePath);
|
|
1124
|
-
if (!rel || rel === "") return filePath;
|
|
1125
|
-
if (rel.startsWith("..")) return filePath;
|
|
1126
|
-
return rel;
|
|
1127
|
-
} catch {
|
|
1128
|
-
return filePath;
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
function formatLocation(fileName, line0, character0) {
|
|
1132
|
-
return `${toProjectRelativeIfPossible(fileName)}:${line0 + 1}:${character0 + 1}`;
|
|
1133
|
-
}
|
|
1134
|
-
function formatGoToDefinitionResult(locations) {
|
|
1135
|
-
if (!locations || locations.length === 0) {
|
|
1136
|
-
return {
|
|
1137
|
-
formatted: "No definition found. This may occur if the cursor is not on a symbol, or if the definition is in an external library not indexed by the LSP server.",
|
|
1138
|
-
resultCount: 0,
|
|
1139
|
-
fileCount: 0
|
|
1140
|
-
};
|
|
1141
|
-
}
|
|
1142
|
-
const fileCount = new Set(locations.map((l) => l.fileName)).size;
|
|
1143
|
-
if (locations.length === 1) {
|
|
1144
|
-
const loc = locations[0];
|
|
1145
|
-
return {
|
|
1146
|
-
formatted: `Defined in ${formatLocation(loc.fileName, loc.line0, loc.character0)}`,
|
|
1147
|
-
resultCount: 1,
|
|
1148
|
-
fileCount
|
|
1149
|
-
};
|
|
1150
|
-
}
|
|
1151
|
-
return {
|
|
1152
|
-
formatted: `Found ${locations.length} definitions:
|
|
1153
|
-
${locations.map(
|
|
1154
|
-
(loc) => ` ${formatLocation(loc.fileName, loc.line0, loc.character0)}`
|
|
1155
|
-
).join("\n")}`,
|
|
1156
|
-
resultCount: locations.length,
|
|
1157
|
-
fileCount
|
|
1158
|
-
};
|
|
1159
|
-
}
|
|
1160
|
-
function groupLocationsByFile(items) {
|
|
1161
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
1162
|
-
for (const item of items) {
|
|
1163
|
-
const key = toProjectRelativeIfPossible(item.fileName);
|
|
1164
|
-
const existing = grouped.get(key);
|
|
1165
|
-
if (existing) existing.push(item);
|
|
1166
|
-
else grouped.set(key, [item]);
|
|
1167
|
-
}
|
|
1168
|
-
return grouped;
|
|
1169
|
-
}
|
|
1170
|
-
function formatFindReferencesResult(references) {
|
|
1171
|
-
if (!references || references.length === 0) {
|
|
1172
|
-
return {
|
|
1173
|
-
formatted: "No references found. This may occur if the symbol has no usages, or if the LSP server has not fully indexed the workspace.",
|
|
1174
|
-
resultCount: 0,
|
|
1175
|
-
fileCount: 0
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
if (references.length === 1) {
|
|
1179
|
-
const ref = references[0];
|
|
1180
|
-
return {
|
|
1181
|
-
formatted: `Found 1 reference:
|
|
1182
|
-
${formatLocation(ref.fileName, ref.line0, ref.character0)}`,
|
|
1183
|
-
resultCount: 1,
|
|
1184
|
-
fileCount: 1
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
|
-
const grouped = groupLocationsByFile(references);
|
|
1188
|
-
const lines = [
|
|
1189
|
-
`Found ${references.length} references across ${grouped.size} files:`
|
|
1190
|
-
];
|
|
1191
|
-
for (const [file, refs] of grouped) {
|
|
1192
|
-
lines.push(`
|
|
1193
|
-
${file}:`);
|
|
1194
|
-
for (const ref of refs) {
|
|
1195
|
-
lines.push(` Line ${ref.line0 + 1}:${ref.character0 + 1}`);
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
return {
|
|
1199
|
-
formatted: lines.join("\n"),
|
|
1200
|
-
resultCount: references.length,
|
|
1201
|
-
fileCount: grouped.size
|
|
1202
|
-
};
|
|
1203
|
-
}
|
|
1204
|
-
function formatHoverResult(hoverText, line0, character0) {
|
|
1205
|
-
if (!hoverText || hoverText.trim() === "") {
|
|
1206
|
-
return {
|
|
1207
|
-
formatted: "No hover information available. This may occur if the cursor is not on a symbol, or if the LSP server has not fully indexed the file.",
|
|
1208
|
-
resultCount: 0,
|
|
1209
|
-
fileCount: 0
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
return {
|
|
1213
|
-
formatted: `Hover info at ${line0 + 1}:${character0 + 1}:
|
|
1214
|
-
|
|
1215
|
-
${hoverText}`,
|
|
1216
|
-
resultCount: 1,
|
|
1217
|
-
fileCount: 1
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
function formatDocumentSymbolsResult(lines, symbolCount) {
|
|
1221
|
-
if (symbolCount === 0) {
|
|
1222
|
-
return {
|
|
1223
|
-
formatted: "No symbols found in document. This may occur if the file is empty, not supported by the LSP server, or if the server has not fully indexed the file.",
|
|
1224
|
-
resultCount: 0,
|
|
1225
|
-
fileCount: 0
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
return {
|
|
1229
|
-
formatted: ["Document symbols:", ...lines].join("\n"),
|
|
1230
|
-
resultCount: symbolCount,
|
|
1231
|
-
fileCount: 1
|
|
1232
|
-
};
|
|
1233
|
-
}
|
|
1234
|
-
var cachedTypeScript = null;
|
|
1235
|
-
function tryLoadTypeScriptModule(projectCwd) {
|
|
1236
|
-
if (cachedTypeScript?.cwd === projectCwd) return cachedTypeScript.module;
|
|
1237
|
-
try {
|
|
1238
|
-
const requireFromCwd = createRequire(
|
|
1239
|
-
pathToFileURL(join2(projectCwd, "__kode_lsp__.js"))
|
|
1240
|
-
);
|
|
1241
|
-
const mod = requireFromCwd("typescript");
|
|
1242
|
-
cachedTypeScript = { cwd: projectCwd, module: mod };
|
|
1243
|
-
return mod;
|
|
1244
|
-
} catch {
|
|
1245
|
-
cachedTypeScript = { cwd: projectCwd, module: null };
|
|
1246
|
-
return null;
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
var projectCache = /* @__PURE__ */ new Map();
|
|
1250
|
-
function getOrCreateTsProject(projectCwd) {
|
|
1251
|
-
const ts = tryLoadTypeScriptModule(projectCwd);
|
|
1252
|
-
if (!ts) return null;
|
|
1253
|
-
const existing = projectCache.get(projectCwd);
|
|
1254
|
-
if (existing) return existing;
|
|
1255
|
-
let compilerOptions = {
|
|
1256
|
-
allowJs: true,
|
|
1257
|
-
checkJs: false,
|
|
1258
|
-
jsx: ts.JsxEmit.ReactJSX,
|
|
1259
|
-
target: ts.ScriptTarget.ESNext,
|
|
1260
|
-
module: ts.ModuleKind.ESNext,
|
|
1261
|
-
moduleResolution: ts.ModuleResolutionKind.NodeNext
|
|
1262
|
-
};
|
|
1263
|
-
let rootFileNames = [];
|
|
1264
|
-
try {
|
|
1265
|
-
const configPath = ts.findConfigFile(
|
|
1266
|
-
projectCwd,
|
|
1267
|
-
ts.sys.fileExists,
|
|
1268
|
-
"tsconfig.json"
|
|
1269
|
-
);
|
|
1270
|
-
if (configPath) {
|
|
1271
|
-
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
1272
|
-
if (!configFile.error) {
|
|
1273
|
-
const parsed = ts.parseJsonConfigFileContent(
|
|
1274
|
-
configFile.config,
|
|
1275
|
-
ts.sys,
|
|
1276
|
-
projectCwd
|
|
1277
|
-
);
|
|
1278
|
-
compilerOptions = { ...compilerOptions, ...parsed.options };
|
|
1279
|
-
rootFileNames = parsed.fileNames;
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
} catch {
|
|
1283
|
-
}
|
|
1284
|
-
const rootFiles = new Set(rootFileNames);
|
|
1285
|
-
const versions = /* @__PURE__ */ new Map();
|
|
1286
|
-
const host = {
|
|
1287
|
-
getCompilationSettings: () => compilerOptions,
|
|
1288
|
-
getScriptFileNames: () => Array.from(rootFiles),
|
|
1289
|
-
getScriptVersion: (fileName) => {
|
|
1290
|
-
try {
|
|
1291
|
-
const stat = statSync(fileName);
|
|
1292
|
-
const version = String(stat.mtimeMs ?? Date.now());
|
|
1293
|
-
versions.set(fileName, version);
|
|
1294
|
-
return version;
|
|
1295
|
-
} catch {
|
|
1296
|
-
return versions.get(fileName) ?? "0";
|
|
1297
|
-
}
|
|
1298
|
-
},
|
|
1299
|
-
getScriptSnapshot: (fileName) => {
|
|
1300
|
-
try {
|
|
1301
|
-
if (!ts.sys.fileExists(fileName)) return void 0;
|
|
1302
|
-
const content = ts.sys.readFile(fileName);
|
|
1303
|
-
if (content === void 0) return void 0;
|
|
1304
|
-
const stat = statSync(fileName);
|
|
1305
|
-
versions.set(fileName, String(stat.mtimeMs ?? Date.now()));
|
|
1306
|
-
return ts.ScriptSnapshot.fromString(content);
|
|
1307
|
-
} catch {
|
|
1308
|
-
return void 0;
|
|
1309
|
-
}
|
|
1310
|
-
},
|
|
1311
|
-
getCurrentDirectory: () => projectCwd,
|
|
1312
|
-
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
|
|
1313
|
-
fileExists: ts.sys.fileExists,
|
|
1314
|
-
readFile: ts.sys.readFile,
|
|
1315
|
-
readDirectory: ts.sys.readDirectory,
|
|
1316
|
-
directoryExists: ts.sys.directoryExists,
|
|
1317
|
-
getDirectories: ts.sys.getDirectories,
|
|
1318
|
-
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
|
|
1319
|
-
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
|
|
1320
|
-
getNewLine: () => ts.sys.newLine
|
|
1321
|
-
};
|
|
1322
|
-
const languageService = ts.createLanguageService(
|
|
1323
|
-
host,
|
|
1324
|
-
ts.createDocumentRegistry()
|
|
1325
|
-
);
|
|
1326
|
-
const state = {
|
|
1327
|
-
ts,
|
|
1328
|
-
cwd: projectCwd,
|
|
1329
|
-
rootFiles,
|
|
1330
|
-
compilerOptions,
|
|
1331
|
-
languageService,
|
|
1332
|
-
versions
|
|
1333
|
-
};
|
|
1334
|
-
projectCache.set(projectCwd, state);
|
|
1335
|
-
return state;
|
|
1336
|
-
}
|
|
1337
|
-
function isFileTypeSupportedByTypescriptBackend(filePath) {
|
|
1338
|
-
const ext = extname(filePath).toLowerCase();
|
|
1339
|
-
return ext === ".ts" || ext === ".tsx" || ext === ".js" || ext === ".jsx" || ext === ".mts" || ext === ".cts" || ext === ".mjs" || ext === ".cjs";
|
|
1340
|
-
}
|
|
1341
|
-
function summarizeToolResult(operation, resultCount, fileCount) {
|
|
1342
|
-
const label = OPERATION_LABELS[operation] ?? {
|
|
1343
|
-
singular: "result",
|
|
1344
|
-
plural: "results"
|
|
1345
|
-
};
|
|
1346
|
-
const noun = resultCount === 1 ? label.singular : label.plural;
|
|
1347
|
-
if (operation === "hover" && resultCount > 0 && label.special) {
|
|
1348
|
-
return /* @__PURE__ */ React4.createElement(Text4, null, "Hover info ", label.special);
|
|
1349
|
-
}
|
|
1350
|
-
return /* @__PURE__ */ React4.createElement(Text4, null, "Found ", /* @__PURE__ */ React4.createElement(Text4, { bold: true }, resultCount), " ", noun, fileCount > 1 ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, " ", "across ", /* @__PURE__ */ React4.createElement(Text4, { bold: true }, fileCount), " files") : null);
|
|
1351
|
-
}
|
|
1352
|
-
var LspTool = {
|
|
1353
|
-
name: TOOL_NAME_FOR_PROMPT2,
|
|
1354
|
-
async description() {
|
|
1355
|
-
return DESCRIPTION3;
|
|
1356
|
-
},
|
|
1357
|
-
async prompt() {
|
|
1358
|
-
return PROMPT3;
|
|
1359
|
-
},
|
|
1360
|
-
inputSchema: inputSchema4,
|
|
1361
|
-
userFacingName() {
|
|
1362
|
-
return "LSP";
|
|
1363
|
-
},
|
|
1364
|
-
async isEnabled() {
|
|
1365
|
-
return tryLoadTypeScriptModule(getCwd()) !== null;
|
|
1366
|
-
},
|
|
1367
|
-
isReadOnly() {
|
|
1368
|
-
return true;
|
|
1369
|
-
},
|
|
1370
|
-
isConcurrencySafe() {
|
|
1371
|
-
return true;
|
|
1372
|
-
},
|
|
1373
|
-
needsPermissions({ filePath }) {
|
|
1374
|
-
const abs = getAbsolutePath(filePath) ?? filePath;
|
|
1375
|
-
return !hasReadPermission(abs || getCwd());
|
|
1376
|
-
},
|
|
1377
|
-
async validateInput(input) {
|
|
1378
|
-
const parsed = inputSchema4.safeParse(input);
|
|
1379
|
-
if (!parsed.success) {
|
|
1380
|
-
return {
|
|
1381
|
-
result: false,
|
|
1382
|
-
message: `Invalid input: ${parsed.error.message}`,
|
|
1383
|
-
errorCode: 3
|
|
1384
|
-
};
|
|
1385
|
-
}
|
|
1386
|
-
const absPath = getAbsolutePath(input.filePath) ?? input.filePath;
|
|
1387
|
-
if (!existsSync2(absPath)) {
|
|
1388
|
-
return {
|
|
1389
|
-
result: false,
|
|
1390
|
-
message: `File does not exist: ${input.filePath}`,
|
|
1391
|
-
errorCode: 1
|
|
1392
|
-
};
|
|
1393
|
-
}
|
|
1394
|
-
try {
|
|
1395
|
-
if (!statSync(absPath).isFile()) {
|
|
1396
|
-
return {
|
|
1397
|
-
result: false,
|
|
1398
|
-
message: `Path is not a file: ${input.filePath}`,
|
|
1399
|
-
errorCode: 2
|
|
1400
|
-
};
|
|
1401
|
-
}
|
|
1402
|
-
} catch (err) {
|
|
1403
|
-
const e = err instanceof Error ? err : new Error(String(err));
|
|
1404
|
-
return {
|
|
1405
|
-
result: false,
|
|
1406
|
-
message: `Cannot access file: ${input.filePath}. ${e.message}`,
|
|
1407
|
-
errorCode: 4
|
|
1408
|
-
};
|
|
1409
|
-
}
|
|
1410
|
-
return { result: true };
|
|
1411
|
-
},
|
|
1412
|
-
renderToolUseMessage(input, { verbose }) {
|
|
1413
|
-
const abs = getAbsolutePath(input.filePath) ?? input.filePath;
|
|
1414
|
-
const filePathForDisplay = verbose ? abs : toProjectRelativeIfPossible(abs);
|
|
1415
|
-
const parts = [];
|
|
1416
|
-
if ((input.operation === "goToDefinition" || input.operation === "findReferences" || input.operation === "hover" || input.operation === "goToImplementation") && input.filePath && input.line !== void 0 && input.character !== void 0) {
|
|
1417
|
-
try {
|
|
1418
|
-
const content = readFileSync2(abs, "utf8");
|
|
1419
|
-
const symbol = extractSymbolAtPosition(
|
|
1420
|
-
content.split("\n"),
|
|
1421
|
-
input.line - 1,
|
|
1422
|
-
input.character - 1
|
|
1423
|
-
);
|
|
1424
|
-
if (symbol) {
|
|
1425
|
-
parts.push(`operation: "${input.operation}"`);
|
|
1426
|
-
parts.push(`symbol: "${symbol}"`);
|
|
1427
|
-
parts.push(`in: "${filePathForDisplay}"`);
|
|
1428
|
-
return parts.join(", ");
|
|
1429
|
-
}
|
|
1430
|
-
} catch {
|
|
1431
|
-
}
|
|
1432
|
-
parts.push(`operation: "${input.operation}"`);
|
|
1433
|
-
parts.push(`file: "${filePathForDisplay}"`);
|
|
1434
|
-
parts.push(`position: ${input.line}:${input.character}`);
|
|
1435
|
-
return parts.join(", ");
|
|
1436
|
-
}
|
|
1437
|
-
parts.push(`operation: "${input.operation}"`);
|
|
1438
|
-
if (input.filePath) parts.push(`file: "${filePathForDisplay}"`);
|
|
1439
|
-
return parts.join(", ");
|
|
1440
|
-
},
|
|
1441
|
-
renderToolUseRejectedMessage() {
|
|
1442
|
-
return /* @__PURE__ */ React4.createElement(FallbackToolUseRejectedMessage, null);
|
|
1443
|
-
},
|
|
1444
|
-
renderToolResultMessage(output, { verbose }) {
|
|
1445
|
-
if (output.resultCount !== void 0 && output.fileCount !== void 0) {
|
|
1446
|
-
const display = verbose ? maybeTruncateVerboseToolOutput(output.result, {
|
|
1447
|
-
maxLines: 120,
|
|
1448
|
-
maxChars: 2e4
|
|
1449
|
-
}) : null;
|
|
1450
|
-
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "row" }, /* @__PURE__ */ React4.createElement(Text4, null, "\xA0\xA0\u23BF \xA0"), summarizeToolResult(
|
|
1451
|
-
output.operation,
|
|
1452
|
-
output.resultCount,
|
|
1453
|
-
output.fileCount
|
|
1454
|
-
)), display ? /* @__PURE__ */ React4.createElement(Box4, { marginLeft: 5 }, /* @__PURE__ */ React4.createElement(Text4, null, display.text)) : null);
|
|
1455
|
-
}
|
|
1456
|
-
return /* @__PURE__ */ React4.createElement(Box4, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "row" }, /* @__PURE__ */ React4.createElement(Text4, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React4.createElement(Text4, null, output.result)));
|
|
1457
|
-
},
|
|
1458
|
-
renderResultForAssistant(output) {
|
|
1459
|
-
return output.result;
|
|
1460
|
-
},
|
|
1461
|
-
async *call(input, _context) {
|
|
1462
|
-
const absPath = getAbsolutePath(input.filePath) ?? input.filePath;
|
|
1463
|
-
if (!isFileTypeSupportedByTypescriptBackend(absPath)) {
|
|
1464
|
-
const ext = extname(absPath);
|
|
1465
|
-
const out = {
|
|
1466
|
-
operation: input.operation,
|
|
1467
|
-
result: `No LSP server available for file type: ${ext}`,
|
|
1468
|
-
filePath: input.filePath,
|
|
1469
|
-
resultCount: 0,
|
|
1470
|
-
fileCount: 0
|
|
1471
|
-
};
|
|
1472
|
-
yield { type: "result", data: out, resultForAssistant: out.result };
|
|
1473
|
-
return;
|
|
1474
|
-
}
|
|
1475
|
-
const project = getOrCreateTsProject(getCwd());
|
|
1476
|
-
if (!project) {
|
|
1477
|
-
const out = {
|
|
1478
|
-
operation: input.operation,
|
|
1479
|
-
result: "LSP server manager not initialized. This may indicate a startup issue.",
|
|
1480
|
-
filePath: input.filePath,
|
|
1481
|
-
resultCount: 0,
|
|
1482
|
-
fileCount: 0
|
|
1483
|
-
};
|
|
1484
|
-
yield { type: "result", data: out, resultForAssistant: out.result };
|
|
1485
|
-
return;
|
|
1486
|
-
}
|
|
1487
|
-
project.rootFiles.add(absPath);
|
|
1488
|
-
const ts = project.ts;
|
|
1489
|
-
const service = project.languageService;
|
|
1490
|
-
const program = service.getProgram?.();
|
|
1491
|
-
if (!program) {
|
|
1492
|
-
const out = {
|
|
1493
|
-
operation: input.operation,
|
|
1494
|
-
result: `Error performing ${input.operation}: TypeScript program not available`,
|
|
1495
|
-
filePath: input.filePath,
|
|
1496
|
-
resultCount: 0,
|
|
1497
|
-
fileCount: 0
|
|
1498
|
-
};
|
|
1499
|
-
yield { type: "result", data: out, resultForAssistant: out.result };
|
|
1500
|
-
return;
|
|
1501
|
-
}
|
|
1502
|
-
const sourceFile = program.getSourceFile(absPath);
|
|
1503
|
-
if (!sourceFile) {
|
|
1504
|
-
const out = {
|
|
1505
|
-
operation: input.operation,
|
|
1506
|
-
result: `Error performing ${input.operation}: File is not part of the TypeScript program`,
|
|
1507
|
-
filePath: input.filePath,
|
|
1508
|
-
resultCount: 0,
|
|
1509
|
-
fileCount: 0
|
|
1510
|
-
};
|
|
1511
|
-
yield { type: "result", data: out, resultForAssistant: out.result };
|
|
1512
|
-
return;
|
|
1513
|
-
}
|
|
1514
|
-
const pos = ts.getPositionOfLineAndCharacter(
|
|
1515
|
-
sourceFile,
|
|
1516
|
-
input.line - 1,
|
|
1517
|
-
input.character - 1
|
|
1518
|
-
);
|
|
1519
|
-
try {
|
|
1520
|
-
let formatted;
|
|
1521
|
-
let resultCount = 0;
|
|
1522
|
-
let fileCount = 0;
|
|
1523
|
-
switch (input.operation) {
|
|
1524
|
-
case "goToDefinition": {
|
|
1525
|
-
const defs = service.getDefinitionAtPosition?.(absPath, pos) ?? [];
|
|
1526
|
-
const locations = defs.map((d) => {
|
|
1527
|
-
const defSourceFile = program.getSourceFile(d.fileName);
|
|
1528
|
-
if (!defSourceFile) return null;
|
|
1529
|
-
const lc = ts.getLineAndCharacterOfPosition(
|
|
1530
|
-
defSourceFile,
|
|
1531
|
-
d.textSpan.start
|
|
1532
|
-
);
|
|
1533
|
-
return {
|
|
1534
|
-
fileName: d.fileName,
|
|
1535
|
-
line0: lc.line,
|
|
1536
|
-
character0: lc.character
|
|
1537
|
-
};
|
|
1538
|
-
}).filter(Boolean);
|
|
1539
|
-
const res = formatGoToDefinitionResult(locations);
|
|
1540
|
-
formatted = res.formatted;
|
|
1541
|
-
resultCount = res.resultCount;
|
|
1542
|
-
fileCount = res.fileCount;
|
|
1543
|
-
break;
|
|
1544
|
-
}
|
|
1545
|
-
case "goToImplementation": {
|
|
1546
|
-
const impls = service.getImplementationAtPosition?.(absPath, pos) ?? [];
|
|
1547
|
-
const locations = impls.map((d) => {
|
|
1548
|
-
const defSourceFile = program.getSourceFile(d.fileName);
|
|
1549
|
-
if (!defSourceFile) return null;
|
|
1550
|
-
const lc = ts.getLineAndCharacterOfPosition(
|
|
1551
|
-
defSourceFile,
|
|
1552
|
-
d.textSpan.start
|
|
1553
|
-
);
|
|
1554
|
-
return {
|
|
1555
|
-
fileName: d.fileName,
|
|
1556
|
-
line0: lc.line,
|
|
1557
|
-
character0: lc.character
|
|
1558
|
-
};
|
|
1559
|
-
}).filter(Boolean);
|
|
1560
|
-
const res = formatGoToDefinitionResult(locations);
|
|
1561
|
-
formatted = res.formatted;
|
|
1562
|
-
resultCount = res.resultCount;
|
|
1563
|
-
fileCount = res.fileCount;
|
|
1564
|
-
break;
|
|
1565
|
-
}
|
|
1566
|
-
case "findReferences": {
|
|
1567
|
-
const referencedSymbols = service.findReferences?.(absPath, pos) ?? [];
|
|
1568
|
-
const refs = [];
|
|
1569
|
-
for (const sym of referencedSymbols) {
|
|
1570
|
-
for (const ref of sym.references ?? []) {
|
|
1571
|
-
const refSource = program.getSourceFile(ref.fileName);
|
|
1572
|
-
if (!refSource) continue;
|
|
1573
|
-
const lc = ts.getLineAndCharacterOfPosition(
|
|
1574
|
-
refSource,
|
|
1575
|
-
ref.textSpan.start
|
|
1576
|
-
);
|
|
1577
|
-
refs.push({
|
|
1578
|
-
fileName: ref.fileName,
|
|
1579
|
-
line0: lc.line,
|
|
1580
|
-
character0: lc.character
|
|
1581
|
-
});
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
const res = formatFindReferencesResult(refs);
|
|
1585
|
-
formatted = res.formatted;
|
|
1586
|
-
resultCount = res.resultCount;
|
|
1587
|
-
fileCount = res.fileCount;
|
|
1588
|
-
break;
|
|
1589
|
-
}
|
|
1590
|
-
case "hover": {
|
|
1591
|
-
const info = service.getQuickInfoAtPosition?.(absPath, pos);
|
|
1592
|
-
let text = null;
|
|
1593
|
-
let hoverLine0 = input.line - 1;
|
|
1594
|
-
let hoverCharacter0 = input.character - 1;
|
|
1595
|
-
if (info) {
|
|
1596
|
-
const parts = [];
|
|
1597
|
-
const signature = ts.displayPartsToString(info.displayParts ?? []);
|
|
1598
|
-
if (signature) parts.push(signature);
|
|
1599
|
-
const doc = ts.displayPartsToString(info.documentation ?? []);
|
|
1600
|
-
if (doc) parts.push(doc);
|
|
1601
|
-
if (info.tags && info.tags.length > 0) {
|
|
1602
|
-
for (const tag of info.tags) {
|
|
1603
|
-
const tagText = ts.displayPartsToString(tag.text ?? []);
|
|
1604
|
-
parts.push(`@${tag.name}${tagText ? ` ${tagText}` : ""}`);
|
|
1605
|
-
}
|
|
1606
|
-
}
|
|
1607
|
-
text = parts.filter(Boolean).join("\n\n");
|
|
1608
|
-
const lc = ts.getLineAndCharacterOfPosition(
|
|
1609
|
-
sourceFile,
|
|
1610
|
-
info.textSpan.start
|
|
1611
|
-
);
|
|
1612
|
-
hoverLine0 = lc.line;
|
|
1613
|
-
hoverCharacter0 = lc.character;
|
|
1614
|
-
}
|
|
1615
|
-
const res = formatHoverResult(text, hoverLine0, hoverCharacter0);
|
|
1616
|
-
formatted = res.formatted;
|
|
1617
|
-
resultCount = res.resultCount;
|
|
1618
|
-
fileCount = res.fileCount;
|
|
1619
|
-
break;
|
|
1620
|
-
}
|
|
1621
|
-
case "documentSymbol": {
|
|
1622
|
-
const tree = service.getNavigationTree?.(absPath);
|
|
1623
|
-
const lines = [];
|
|
1624
|
-
let count = 0;
|
|
1625
|
-
const kindLabel = (kind) => {
|
|
1626
|
-
const m = {
|
|
1627
|
-
class: "Class",
|
|
1628
|
-
interface: "Interface",
|
|
1629
|
-
enum: "Enum",
|
|
1630
|
-
function: "Function",
|
|
1631
|
-
method: "Method",
|
|
1632
|
-
property: "Property",
|
|
1633
|
-
var: "Variable",
|
|
1634
|
-
let: "Variable",
|
|
1635
|
-
const: "Constant",
|
|
1636
|
-
module: "Module",
|
|
1637
|
-
alias: "Alias",
|
|
1638
|
-
type: "Type"
|
|
1639
|
-
};
|
|
1640
|
-
return m[kind] ?? (kind ? kind[0].toUpperCase() + kind.slice(1) : "Unknown");
|
|
1641
|
-
};
|
|
1642
|
-
const walk = (node, depth) => {
|
|
1643
|
-
const children = node?.childItems ?? [];
|
|
1644
|
-
for (const child of children) {
|
|
1645
|
-
const span = child.spans?.[0];
|
|
1646
|
-
if (!span) continue;
|
|
1647
|
-
const lc = ts.getLineAndCharacterOfPosition(
|
|
1648
|
-
sourceFile,
|
|
1649
|
-
span.start
|
|
1650
|
-
);
|
|
1651
|
-
const indent = " ".repeat(depth);
|
|
1652
|
-
const label = kindLabel(child.kind);
|
|
1653
|
-
const detail = child.kindModifiers ? ` ${child.kindModifiers}` : "";
|
|
1654
|
-
lines.push(
|
|
1655
|
-
`${indent}${child.text} (${label})${detail} - Line ${lc.line + 1}`
|
|
1656
|
-
);
|
|
1657
|
-
count += 1;
|
|
1658
|
-
if (child.childItems && child.childItems.length > 0) {
|
|
1659
|
-
walk(child, depth + 1);
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
};
|
|
1663
|
-
walk(tree, 0);
|
|
1664
|
-
const res = formatDocumentSymbolsResult(lines, count);
|
|
1665
|
-
formatted = res.formatted;
|
|
1666
|
-
resultCount = res.resultCount;
|
|
1667
|
-
fileCount = res.fileCount;
|
|
1668
|
-
break;
|
|
1669
|
-
}
|
|
1670
|
-
case "workspaceSymbol": {
|
|
1671
|
-
const items = service.getNavigateToItems?.("", 100, void 0, true, true) ?? [];
|
|
1672
|
-
if (!items || items.length === 0) {
|
|
1673
|
-
formatted = "No symbols found in workspace. This may occur if the workspace is empty, or if the LSP server has not finished indexing the project.";
|
|
1674
|
-
resultCount = 0;
|
|
1675
|
-
fileCount = 0;
|
|
1676
|
-
break;
|
|
1677
|
-
}
|
|
1678
|
-
const lines = [
|
|
1679
|
-
`Found ${items.length} symbol${items.length === 1 ? "" : "s"} in workspace:`
|
|
1680
|
-
];
|
|
1681
|
-
const grouped = groupLocationsByFile(
|
|
1682
|
-
items.map((it) => ({
|
|
1683
|
-
fileName: it.fileName,
|
|
1684
|
-
item: it
|
|
1685
|
-
}))
|
|
1686
|
-
);
|
|
1687
|
-
for (const [file, itemsInFile] of grouped) {
|
|
1688
|
-
lines.push(`
|
|
1689
|
-
${file}:`);
|
|
1690
|
-
for (const wrapper of itemsInFile) {
|
|
1691
|
-
const it = wrapper.item;
|
|
1692
|
-
const sf = program.getSourceFile(it.fileName);
|
|
1693
|
-
if (!sf) continue;
|
|
1694
|
-
const span = it.textSpan;
|
|
1695
|
-
const lc = span ? ts.getLineAndCharacterOfPosition(sf, span.start) : { line: 0, character: 0 };
|
|
1696
|
-
const label = it.kind ? String(it.kind)[0].toUpperCase() + String(it.kind).slice(1) : "Symbol";
|
|
1697
|
-
let line = ` ${it.name} (${label}) - Line ${lc.line + 1}`;
|
|
1698
|
-
if (it.containerName) line += ` in ${it.containerName}`;
|
|
1699
|
-
lines.push(line);
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
formatted = lines.join("\n");
|
|
1703
|
-
resultCount = items.length;
|
|
1704
|
-
fileCount = grouped.size;
|
|
1705
|
-
break;
|
|
1706
|
-
}
|
|
1707
|
-
case "prepareCallHierarchy":
|
|
1708
|
-
case "incomingCalls":
|
|
1709
|
-
case "outgoingCalls": {
|
|
1710
|
-
const opLabel = input.operation;
|
|
1711
|
-
formatted = `Error performing ${opLabel}: Call hierarchy is not supported by the TypeScript backend`;
|
|
1712
|
-
resultCount = 0;
|
|
1713
|
-
fileCount = 0;
|
|
1714
|
-
break;
|
|
1715
|
-
}
|
|
1716
|
-
default: {
|
|
1717
|
-
formatted = `Error performing ${input.operation}: Unsupported operation`;
|
|
1718
|
-
resultCount = 0;
|
|
1719
|
-
fileCount = 0;
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
const out = {
|
|
1723
|
-
operation: input.operation,
|
|
1724
|
-
result: formatted,
|
|
1725
|
-
filePath: input.filePath,
|
|
1726
|
-
resultCount,
|
|
1727
|
-
fileCount
|
|
1728
|
-
};
|
|
1729
|
-
yield { type: "result", data: out, resultForAssistant: out.result };
|
|
1730
|
-
} catch (err) {
|
|
1731
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1732
|
-
const out = {
|
|
1733
|
-
operation: input.operation,
|
|
1734
|
-
result: `Error performing ${input.operation}: ${message}`,
|
|
1735
|
-
filePath: input.filePath
|
|
1736
|
-
};
|
|
1737
|
-
yield { type: "result", data: out, resultForAssistant: out.result };
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
};
|
|
1741
|
-
|
|
1742
|
-
// src/tools/mcp/ReadMcpResourceTool/ReadMcpResourceTool.tsx
|
|
1743
|
-
import { Box as Box5, Text as Text5 } from "ink";
|
|
1744
|
-
import React5 from "react";
|
|
1745
|
-
import { z as z5 } from "zod";
|
|
1746
|
-
import { ReadResourceResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
1747
|
-
|
|
1748
|
-
// src/tools/mcp/ReadMcpResourceTool/prompt.ts
|
|
1749
|
-
var TOOL_NAME2 = "ReadMcpResourceTool";
|
|
1750
|
-
var DESCRIPTION4 = `Reads a specific resource from an MCP server.
|
|
1751
|
-
- server: The name of the MCP server to read from
|
|
1752
|
-
- uri: The URI of the resource to read
|
|
1753
|
-
|
|
1754
|
-
Usage examples:
|
|
1755
|
-
- Read a resource from a server: \`readMcpResource({ server: "myserver", uri: "my-resource-uri" })\``;
|
|
1756
|
-
var PROMPT4 = `Reads a specific resource from an MCP server, identified by server name and resource URI.
|
|
1757
|
-
|
|
1758
|
-
Parameters:
|
|
1759
|
-
- server (required): The name of the MCP server from which to read the resource
|
|
1760
|
-
- uri (required): The URI of the resource to read`;
|
|
1761
|
-
|
|
1762
|
-
// src/tools/mcp/ReadMcpResourceTool/ReadMcpResourceTool.tsx
|
|
1763
|
-
var inputSchema5 = z5.strictObject({
|
|
1764
|
-
server: z5.string().describe("The MCP server name"),
|
|
1765
|
-
uri: z5.string().describe("The resource URI to read")
|
|
1766
|
-
});
|
|
1767
|
-
var ReadMcpResourceTool = {
|
|
1768
|
-
name: TOOL_NAME2,
|
|
1769
|
-
async description() {
|
|
1770
|
-
return DESCRIPTION4;
|
|
1771
|
-
},
|
|
1772
|
-
async prompt() {
|
|
1773
|
-
return PROMPT4;
|
|
1774
|
-
},
|
|
1775
|
-
inputSchema: inputSchema5,
|
|
1776
|
-
userFacingName() {
|
|
1777
|
-
return "readMcpResource";
|
|
1778
|
-
},
|
|
1779
|
-
async isEnabled() {
|
|
1780
|
-
return true;
|
|
1781
|
-
},
|
|
1782
|
-
isReadOnly() {
|
|
1783
|
-
return true;
|
|
1784
|
-
},
|
|
1785
|
-
isConcurrencySafe() {
|
|
1786
|
-
return true;
|
|
1787
|
-
},
|
|
1788
|
-
needsPermissions() {
|
|
1789
|
-
return false;
|
|
1790
|
-
},
|
|
1791
|
-
async validateInput({ server }, context) {
|
|
1792
|
-
const clients = context?.options?.mcpClients ?? await getClients();
|
|
1793
|
-
const match = clients.find((c) => c.name === server);
|
|
1794
|
-
if (!match) {
|
|
1795
|
-
return {
|
|
1796
|
-
result: false,
|
|
1797
|
-
message: `Server "${server}" not found. Available servers: ${clients.map((c) => c.name).join(", ")}`,
|
|
1798
|
-
errorCode: 1
|
|
1799
|
-
};
|
|
1800
|
-
}
|
|
1801
|
-
if (match.type !== "connected") {
|
|
1802
|
-
return {
|
|
1803
|
-
result: false,
|
|
1804
|
-
message: `Server "${server}" is not connected`,
|
|
1805
|
-
errorCode: 2
|
|
1806
|
-
};
|
|
1807
|
-
}
|
|
1808
|
-
let capabilities = match.capabilities ?? null;
|
|
1809
|
-
if (!capabilities) {
|
|
1810
|
-
try {
|
|
1811
|
-
capabilities = match.client.getServerCapabilities();
|
|
1812
|
-
} catch {
|
|
1813
|
-
capabilities = null;
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
if (!capabilities?.resources) {
|
|
1817
|
-
return {
|
|
1818
|
-
result: false,
|
|
1819
|
-
message: `Server "${server}" does not support resources`,
|
|
1820
|
-
errorCode: 3
|
|
1821
|
-
};
|
|
1822
|
-
}
|
|
1823
|
-
return { result: true };
|
|
1824
|
-
},
|
|
1825
|
-
renderToolUseMessage({ server, uri }) {
|
|
1826
|
-
if (!server || !uri) return null;
|
|
1827
|
-
return `Read resource "${uri}" from server "${server}"`;
|
|
1828
|
-
},
|
|
1829
|
-
renderToolUseRejectedMessage() {
|
|
1830
|
-
return /* @__PURE__ */ React5.createElement(FallbackToolUseRejectedMessage, null);
|
|
1831
|
-
},
|
|
1832
|
-
renderToolResultMessage(output) {
|
|
1833
|
-
const count = output.contents?.length ?? 0;
|
|
1834
|
-
return /* @__PURE__ */ React5.createElement(Box5, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "row" }, /* @__PURE__ */ React5.createElement(Text5, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React5.createElement(Text5, { bold: true }, "Read MCP resource"), /* @__PURE__ */ React5.createElement(Text5, null, count ? ` (${count} part${count === 1 ? "" : "s"})` : "")), /* @__PURE__ */ React5.createElement(Cost, { costUSD: 0, durationMs: 0, debug: false }));
|
|
1835
|
-
},
|
|
1836
|
-
renderResultForAssistant(output) {
|
|
1837
|
-
return JSON.stringify(output);
|
|
1838
|
-
},
|
|
1839
|
-
async *call({ server, uri }, context) {
|
|
1840
|
-
const clients = context.options?.mcpClients ?? await getClients();
|
|
1841
|
-
const match = clients.find((c) => c.name === server);
|
|
1842
|
-
if (!match) {
|
|
1843
|
-
throw new Error(
|
|
1844
|
-
`Server "${server}" not found. Available servers: ${clients.map((c) => c.name).join(", ")}`
|
|
1845
|
-
);
|
|
1846
|
-
}
|
|
1847
|
-
if (match.type !== "connected") {
|
|
1848
|
-
throw new Error(`Server "${server}" is not connected`);
|
|
1849
|
-
}
|
|
1850
|
-
let capabilities = match.capabilities ?? null;
|
|
1851
|
-
if (!capabilities) {
|
|
1852
|
-
try {
|
|
1853
|
-
capabilities = match.client.getServerCapabilities();
|
|
1854
|
-
} catch {
|
|
1855
|
-
capabilities = null;
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
if (!capabilities?.resources) {
|
|
1859
|
-
throw new Error(`Server "${server}" does not support resources`);
|
|
1860
|
-
}
|
|
1861
|
-
const result = await match.client.request(
|
|
1862
|
-
{ method: "resources/read", params: { uri } },
|
|
1863
|
-
ReadResourceResultSchema
|
|
1864
|
-
);
|
|
1865
|
-
yield {
|
|
1866
|
-
type: "result",
|
|
1867
|
-
data: result,
|
|
1868
|
-
resultForAssistant: this.renderResultForAssistant(result)
|
|
1869
|
-
};
|
|
1870
|
-
}
|
|
1871
|
-
};
|
|
1872
|
-
|
|
1873
|
-
// src/tools/agent/TaskTool/TaskTool.tsx
|
|
1874
|
-
import { last, memoize } from "lodash-es";
|
|
1875
|
-
import React6 from "react";
|
|
1876
|
-
import { Box as Box6, Text as Text6 } from "ink";
|
|
1877
|
-
import { z as z6 } from "zod";
|
|
1878
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
1879
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
1880
|
-
|
|
1881
|
-
// src/utils/agent/transcripts.ts
|
|
1882
|
-
var transcripts = /* @__PURE__ */ new Map();
|
|
1883
|
-
function saveAgentTranscript(agentId, messages) {
|
|
1884
|
-
transcripts.set(agentId, messages);
|
|
1885
|
-
}
|
|
1886
|
-
function getAgentTranscript(agentId) {
|
|
1887
|
-
return transcripts.get(agentId);
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
// src/tools/agent/TaskTool/prompt.ts
|
|
1891
|
-
var SUBAGENT_DISALLOWED_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1892
|
-
"Task",
|
|
1893
|
-
"TaskOutput",
|
|
1894
|
-
"KillShell",
|
|
1895
|
-
"EnterPlanMode",
|
|
1896
|
-
"ExitPlanMode",
|
|
1897
|
-
"AskUserQuestion"
|
|
1898
|
-
]);
|
|
1899
|
-
async function getTaskTools(safeMode) {
|
|
1900
|
-
return (await (!safeMode ? getTools() : getReadOnlyTools())).filter(
|
|
1901
|
-
(tool) => !SUBAGENT_DISALLOWED_TOOL_NAMES.has(tool.name)
|
|
1902
|
-
);
|
|
1903
|
-
}
|
|
1904
|
-
async function getPrompt(safeMode) {
|
|
1905
|
-
const agents = await getActiveAgents();
|
|
1906
|
-
const agentDescriptions = agents.map((agent) => {
|
|
1907
|
-
const toolsStr = Array.isArray(agent.tools) ? agent.tools.join(", ") : "*";
|
|
1908
|
-
return `- ${agent.agentType}: ${agent.whenToUse} (Tools: ${toolsStr})`;
|
|
1909
|
-
}).join("\n");
|
|
1910
|
-
return `Launch a new agent to handle complex, multi-step tasks autonomously.
|
|
1911
|
-
|
|
1912
|
-
Available agent types and the tools they have access to:
|
|
1913
|
-
${agentDescriptions}
|
|
1914
|
-
|
|
1915
|
-
When using the Task tool, you must specify a subagent_type parameter to select which agent type to use.
|
|
1916
|
-
|
|
1917
|
-
When to use the Agent tool:
|
|
1918
|
-
- When you are instructed to execute custom slash commands. Use the Agent tool with the slash command invocation as the entire prompt. The slash command can take arguments. For example: Task(description="Check the file", prompt="/check-file path/to/file.py")
|
|
1919
|
-
|
|
1920
|
-
When NOT to use the Agent tool:
|
|
1921
|
-
- If you want to read a specific file path, use the ${FileReadTool.name} or ${GlobTool.name} tool instead of the Agent tool, to find the match more quickly
|
|
1922
|
-
- If you are searching for a specific class definition like "class Foo", use the ${GlobTool.name} tool instead, to find the match more quickly
|
|
1923
|
-
- If you are searching for code within a specific file or set of 2-3 files, use the ${FileReadTool.name} tool instead of the Agent tool, to find the match more quickly
|
|
1924
|
-
- Other tasks that are not related to the agent descriptions above
|
|
1925
|
-
|
|
1926
|
-
Usage notes:
|
|
1927
|
-
1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
|
|
1928
|
-
2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.
|
|
1929
|
-
3. Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
|
|
1930
|
-
4. The agent's outputs should generally be trusted
|
|
1931
|
-
5. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent
|
|
1932
|
-
6. If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.
|
|
1933
|
-
|
|
1934
|
-
Example usage:
|
|
1935
|
-
|
|
1936
|
-
<example_agent_descriptions>
|
|
1937
|
-
"code-reviewer": use this agent after you are done writing a signficant piece of code
|
|
1938
|
-
"greeting-responder": use this agent when to respond to user greetings with a friendly joke
|
|
1939
|
-
</example_agent_description>
|
|
1940
|
-
|
|
1941
|
-
<example>
|
|
1942
|
-
user: "Please write a function that checks if a number is prime"
|
|
1943
|
-
assistant: Sure let me write a function that checks if a number is prime
|
|
1944
|
-
assistant: First let me use the ${FileWriteTool.name} tool to write a function that checks if a number is prime
|
|
1945
|
-
assistant: I'm going to use the ${FileWriteTool.name} tool to write the following code:
|
|
1946
|
-
<code>
|
|
1947
|
-
function isPrime(n) {
|
|
1948
|
-
if (n <= 1) return false
|
|
1949
|
-
for (let i = 2; i * i <= n; i++) {
|
|
1950
|
-
if (n % i === 0) return false
|
|
1951
|
-
}
|
|
1952
|
-
return true
|
|
1953
|
-
}
|
|
1954
|
-
</code>
|
|
1955
|
-
<commentary>
|
|
1956
|
-
Since a signficant piece of code was written and the task was completed, now use the code-reviewer agent to review the code
|
|
1957
|
-
</commentary>
|
|
1958
|
-
assistant: Now let me use the code-reviewer agent to review the code
|
|
1959
|
-
assistant: Uses the Task tool to launch the with the code-reviewer agent
|
|
1960
|
-
</example>
|
|
1961
|
-
|
|
1962
|
-
<example>
|
|
1963
|
-
user: "Hello"
|
|
1964
|
-
<commentary>
|
|
1965
|
-
Since the user is greeting, use the greeting-responder agent to respond with a friendly joke
|
|
1966
|
-
</commentary>
|
|
1967
|
-
assistant: "I'm going to use the Task tool to launch the with the greeting-responder agent"
|
|
1968
|
-
</example>`;
|
|
1969
|
-
}
|
|
1970
|
-
|
|
1971
|
-
// src/tools/agent/TaskTool/constants.ts
|
|
1972
|
-
var TOOL_NAME3 = "Task";
|
|
1973
|
-
|
|
1974
|
-
// src/tools/agent/TaskTool/TaskTool.tsx
|
|
1975
|
-
var inputSchema6 = z6.object({
|
|
1976
|
-
description: z6.string().describe("A short (3-5 word) description of the task"),
|
|
1977
|
-
prompt: z6.string().describe("The task for the agent to perform"),
|
|
1978
|
-
subagent_type: z6.string().describe("The type of specialized agent to use for this task"),
|
|
1979
|
-
model: z6.enum(["sonnet", "opus", "haiku"]).optional().describe(
|
|
1980
|
-
"Optional model to use for this agent. If not specified, inherits from parent. Prefer haiku for quick, straightforward tasks to minimize cost and latency."
|
|
1981
|
-
),
|
|
1982
|
-
resume: z6.string().optional().describe(
|
|
1983
|
-
"Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript."
|
|
1984
|
-
),
|
|
1985
|
-
run_in_background: z6.boolean().optional().describe(
|
|
1986
|
-
"Set to true to run this agent in the background. Use TaskOutput to read the output later."
|
|
1987
|
-
)
|
|
1988
|
-
});
|
|
1989
|
-
function modelEnumToPointer(model) {
|
|
1990
|
-
if (!model) return void 0;
|
|
1991
|
-
switch (model) {
|
|
1992
|
-
case "haiku":
|
|
1993
|
-
return "quick";
|
|
1994
|
-
case "sonnet":
|
|
1995
|
-
return "task";
|
|
1996
|
-
case "opus":
|
|
1997
|
-
return "main";
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
function normalizeAgentModelName(model) {
|
|
2001
|
-
if (!model) return void 0;
|
|
2002
|
-
if (model === "inherit") return "inherit";
|
|
2003
|
-
if (model === "haiku" || model === "sonnet" || model === "opus") {
|
|
2004
|
-
return modelEnumToPointer(model);
|
|
2005
|
-
}
|
|
2006
|
-
return model;
|
|
2007
|
-
}
|
|
2008
|
-
function getToolNameFromSpec(spec) {
|
|
2009
|
-
const trimmed = spec.trim();
|
|
2010
|
-
if (!trimmed) return trimmed;
|
|
2011
|
-
const match = trimmed.match(/^([^(]+)\(([^)]+)\)$/);
|
|
2012
|
-
if (!match) return trimmed;
|
|
2013
|
-
const toolName = match[1]?.trim();
|
|
2014
|
-
const ruleContent = match[2]?.trim();
|
|
2015
|
-
if (!toolName || !ruleContent) return trimmed;
|
|
2016
|
-
return toolName;
|
|
2017
|
-
}
|
|
2018
|
-
function asyncLaunchMessage(agentId) {
|
|
2019
|
-
const toolName = "TaskOutput";
|
|
2020
|
-
return `Async agent launched successfully.
|
|
2021
|
-
agentId: ${agentId} (This is an internal ID for your use, do not mention it to the user. Use this ID to retrieve results with ${toolName} when the agent finishes).
|
|
2022
|
-
The agent is currently working in the background. If you have other tasks you you should continue working on them now. Wait to call ${toolName} until either:
|
|
2023
|
-
- If you want to check on the agent's progress - call ${toolName} with block=false to get an immediate update on the agent's status
|
|
2024
|
-
- If you run out of things to do and the agent is still running - call ${toolName} with block=true to idle and wait for the agent's result (do not use block=true unless you completely run out of things to do as it will waste time).`;
|
|
2025
|
-
}
|
|
2026
|
-
var FORK_CONTEXT_TOOL_RESULT_TEXT = `### FORKING CONVERSATION CONTEXT ###
|
|
2027
|
-
### ENTERING SUB-AGENT ROUTINE ###
|
|
2028
|
-
Entered sub-agent context
|
|
2029
|
-
|
|
2030
|
-
PLEASE NOTE:
|
|
2031
|
-
- The messages above this point are from the main thread prior to sub-agent execution. They are provided as context only.
|
|
2032
|
-
- Context messages may include tool_use blocks for tools that are not available in the sub-agent context. You should only use the tools specifically provided to you in the system prompt.
|
|
2033
|
-
- Only complete the specific sub-agent task you have been assigned below.`;
|
|
2034
|
-
function normalizeAgentPermissionMode(mode) {
|
|
2035
|
-
if (typeof mode !== "string") return void 0;
|
|
2036
|
-
const trimmed = mode.trim();
|
|
2037
|
-
if (!trimmed) return void 0;
|
|
2038
|
-
if (trimmed === "delegate") return "default";
|
|
2039
|
-
if (trimmed === "default" || trimmed === "acceptEdits" || trimmed === "plan" || trimmed === "bypassPermissions" || trimmed === "dontAsk") {
|
|
2040
|
-
return trimmed;
|
|
2041
|
-
}
|
|
2042
|
-
return void 0;
|
|
2043
|
-
}
|
|
2044
|
-
function applyAgentPermissionMode(base, options) {
|
|
2045
|
-
if (!base) return base;
|
|
2046
|
-
if (!options.agentPermissionMode) return base;
|
|
2047
|
-
if (options.agentPermissionMode === "bypassPermissions" && (options.safeMode || base.isBypassPermissionsModeAvailable !== true)) {
|
|
2048
|
-
return { ...base, mode: "default" };
|
|
2049
|
-
}
|
|
2050
|
-
return { ...base, mode: options.agentPermissionMode };
|
|
2051
|
-
}
|
|
2052
|
-
function readJsonArrayFile(path) {
|
|
2053
|
-
if (!existsSync3(path)) return null;
|
|
2054
|
-
try {
|
|
2055
|
-
const raw = readFileSync3(path, "utf8");
|
|
2056
|
-
const parsed = JSON.parse(raw);
|
|
2057
|
-
return Array.isArray(parsed) ? parsed : null;
|
|
2058
|
-
} catch {
|
|
2059
|
-
return null;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
function buildForkContextForAgent(options) {
|
|
2063
|
-
const userPromptMessage = createUserMessage(options.prompt);
|
|
2064
|
-
if (!options.enabled || !options.toolUseId) {
|
|
2065
|
-
return {
|
|
2066
|
-
forkContextMessages: [],
|
|
2067
|
-
promptMessages: [userPromptMessage]
|
|
2068
|
-
};
|
|
2069
|
-
}
|
|
2070
|
-
const mainPath = getMessagesPath(options.messageLogName, options.forkNumber, 0);
|
|
2071
|
-
const mainMessages = readJsonArrayFile(mainPath);
|
|
2072
|
-
if (!mainMessages || mainMessages.length === 0) {
|
|
2073
|
-
return {
|
|
2074
|
-
forkContextMessages: [],
|
|
2075
|
-
promptMessages: [userPromptMessage]
|
|
2076
|
-
};
|
|
2077
|
-
}
|
|
2078
|
-
let toolUseMessageIndex = -1;
|
|
2079
|
-
let toolUseMessage = null;
|
|
2080
|
-
let taskToolUseBlock = null;
|
|
2081
|
-
for (let i = 0; i < mainMessages.length; i++) {
|
|
2082
|
-
const msg = mainMessages[i];
|
|
2083
|
-
if (msg?.type !== "assistant") continue;
|
|
2084
|
-
const blocks = Array.isArray(msg?.message?.content) ? msg.message.content : [];
|
|
2085
|
-
const match = blocks.find(
|
|
2086
|
-
(b) => b && b.type === "tool_use" && b.id === options.toolUseId
|
|
2087
|
-
);
|
|
2088
|
-
if (!match) continue;
|
|
2089
|
-
toolUseMessageIndex = i;
|
|
2090
|
-
toolUseMessage = msg;
|
|
2091
|
-
taskToolUseBlock = match;
|
|
2092
|
-
break;
|
|
2093
|
-
}
|
|
2094
|
-
if (toolUseMessageIndex === -1 || !toolUseMessage || !taskToolUseBlock) {
|
|
2095
|
-
return {
|
|
2096
|
-
forkContextMessages: [],
|
|
2097
|
-
promptMessages: [userPromptMessage]
|
|
2098
|
-
};
|
|
2099
|
-
}
|
|
2100
|
-
const forkContextMessages = mainMessages.slice(
|
|
2101
|
-
0,
|
|
2102
|
-
toolUseMessageIndex
|
|
2103
|
-
) ?? [];
|
|
2104
|
-
const toolUseOnlyAssistant = {
|
|
2105
|
-
...toolUseMessage,
|
|
2106
|
-
uuid: randomUUID2(),
|
|
2107
|
-
message: {
|
|
2108
|
-
...toolUseMessage.message,
|
|
2109
|
-
content: [taskToolUseBlock]
|
|
2110
|
-
}
|
|
2111
|
-
};
|
|
2112
|
-
const forkContextToolResult = createUserMessage(
|
|
2113
|
-
[
|
|
2114
|
-
{
|
|
2115
|
-
type: "tool_result",
|
|
2116
|
-
tool_use_id: taskToolUseBlock.id,
|
|
2117
|
-
content: FORK_CONTEXT_TOOL_RESULT_TEXT
|
|
2118
|
-
}
|
|
2119
|
-
],
|
|
2120
|
-
{
|
|
2121
|
-
data: {
|
|
2122
|
-
status: "sub_agent_entered",
|
|
2123
|
-
description: "Entered sub-agent context",
|
|
2124
|
-
message: FORK_CONTEXT_TOOL_RESULT_TEXT
|
|
2125
|
-
},
|
|
2126
|
-
resultForAssistant: FORK_CONTEXT_TOOL_RESULT_TEXT
|
|
2127
|
-
}
|
|
2128
|
-
);
|
|
2129
|
-
return {
|
|
2130
|
-
forkContextMessages,
|
|
2131
|
-
promptMessages: [toolUseOnlyAssistant, forkContextToolResult, userPromptMessage]
|
|
2132
|
-
};
|
|
2133
|
-
}
|
|
2134
|
-
var TaskTool = {
|
|
2135
|
-
name: TOOL_NAME3,
|
|
2136
|
-
inputSchema: inputSchema6,
|
|
2137
|
-
async description() {
|
|
2138
|
-
return "Launch a new task";
|
|
2139
|
-
},
|
|
2140
|
-
async prompt({ safeMode }) {
|
|
2141
|
-
return await getPrompt(safeMode);
|
|
2142
|
-
},
|
|
2143
|
-
userFacingName(input) {
|
|
2144
|
-
if (input?.subagent_type && input.subagent_type !== "general-purpose") {
|
|
2145
|
-
return input.subagent_type;
|
|
2146
|
-
}
|
|
2147
|
-
return "Task";
|
|
2148
|
-
},
|
|
2149
|
-
async isEnabled() {
|
|
2150
|
-
return true;
|
|
2151
|
-
},
|
|
2152
|
-
isReadOnly() {
|
|
2153
|
-
return true;
|
|
2154
|
-
},
|
|
2155
|
-
isConcurrencySafe() {
|
|
2156
|
-
return true;
|
|
2157
|
-
},
|
|
2158
|
-
needsPermissions() {
|
|
2159
|
-
return false;
|
|
2160
|
-
},
|
|
2161
|
-
async validateInput(input) {
|
|
2162
|
-
if (!input.description || typeof input.description !== "string") {
|
|
2163
|
-
return {
|
|
2164
|
-
result: false,
|
|
2165
|
-
message: "Description is required and must be a string"
|
|
2166
|
-
};
|
|
2167
|
-
}
|
|
2168
|
-
if (!input.prompt || typeof input.prompt !== "string") {
|
|
2169
|
-
return {
|
|
2170
|
-
result: false,
|
|
2171
|
-
message: "Prompt is required and must be a string"
|
|
2172
|
-
};
|
|
2173
|
-
}
|
|
2174
|
-
const availableTypes = await getAvailableAgentTypes();
|
|
2175
|
-
if (!availableTypes.includes(input.subagent_type)) {
|
|
2176
|
-
return {
|
|
2177
|
-
result: false,
|
|
2178
|
-
message: `Agent type '${input.subagent_type}' not found. Available agents: ${availableTypes.join(", ")}`,
|
|
2179
|
-
meta: { subagent_type: input.subagent_type, availableTypes }
|
|
2180
|
-
};
|
|
2181
|
-
}
|
|
2182
|
-
if (input.resume) {
|
|
2183
|
-
const transcript = getAgentTranscript(input.resume);
|
|
2184
|
-
if (!transcript) {
|
|
2185
|
-
return {
|
|
2186
|
-
result: false,
|
|
2187
|
-
message: `No transcript found for agent ID: ${input.resume}`,
|
|
2188
|
-
meta: { resume: input.resume }
|
|
2189
|
-
};
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
return { result: true };
|
|
2193
|
-
},
|
|
2194
|
-
renderToolUseMessage({ description, prompt }) {
|
|
2195
|
-
if (!description || !prompt) return "";
|
|
2196
|
-
return description;
|
|
2197
|
-
},
|
|
2198
|
-
renderToolUseRejectedMessage() {
|
|
2199
|
-
return /* @__PURE__ */ React6.createElement(FallbackToolUseRejectedMessage, null);
|
|
2200
|
-
},
|
|
2201
|
-
renderToolResultMessage(output, { verbose }) {
|
|
2202
|
-
const theme = getTheme();
|
|
2203
|
-
if (output.status === "async_launched") {
|
|
2204
|
-
const hint = output.prompt ? " (down arrow \u2193 to manage \xB7 ctrl+o to expand)" : " (down arrow \u2193 to manage)";
|
|
2205
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "row" }, /* @__PURE__ */ React6.createElement(Text6, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React6.createElement(Text6, null, "Backgrounded agent", !verbose && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, hint))), verbose && output.prompt && /* @__PURE__ */ React6.createElement(
|
|
2206
|
-
Box6,
|
|
2207
|
-
{
|
|
2208
|
-
paddingLeft: 2,
|
|
2209
|
-
borderLeftStyle: "single",
|
|
2210
|
-
borderLeftColor: theme.secondaryBorder
|
|
2211
|
-
},
|
|
2212
|
-
/* @__PURE__ */ React6.createElement(Text6, { color: theme.secondaryText, wrap: "wrap" }, output.prompt)
|
|
2213
|
-
));
|
|
2214
|
-
}
|
|
2215
|
-
const summary = [
|
|
2216
|
-
output.totalToolUseCount === 1 ? "1 tool use" : `${output.totalToolUseCount} tool uses`,
|
|
2217
|
-
`${formatNumber(output.totalTokens)} tokens`,
|
|
2218
|
-
formatDuration(output.totalDurationMs)
|
|
2219
|
-
];
|
|
2220
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, verbose && output.prompt && /* @__PURE__ */ React6.createElement(
|
|
2221
|
-
Box6,
|
|
2222
|
-
{
|
|
2223
|
-
paddingLeft: 2,
|
|
2224
|
-
borderLeftStyle: "single",
|
|
2225
|
-
borderLeftColor: theme.secondaryBorder
|
|
2226
|
-
},
|
|
2227
|
-
/* @__PURE__ */ React6.createElement(Text6, { color: theme.secondaryText, wrap: "wrap" }, maybeTruncateVerboseToolOutput(output.prompt, {
|
|
2228
|
-
maxLines: 120,
|
|
2229
|
-
maxChars: 2e4
|
|
2230
|
-
}).text)
|
|
2231
|
-
), verbose && output.content.length > 0 && /* @__PURE__ */ React6.createElement(
|
|
2232
|
-
Box6,
|
|
2233
|
-
{
|
|
2234
|
-
paddingLeft: 2,
|
|
2235
|
-
borderLeftStyle: "single",
|
|
2236
|
-
borderLeftColor: theme.secondaryBorder
|
|
2237
|
-
},
|
|
2238
|
-
/* @__PURE__ */ React6.createElement(Text6, { wrap: "wrap" }, maybeTruncateVerboseToolOutput(
|
|
2239
|
-
output.content.map((b) => b.text).join("\n"),
|
|
2240
|
-
{
|
|
2241
|
-
maxLines: 200,
|
|
2242
|
-
maxChars: 4e4
|
|
2243
|
-
}
|
|
2244
|
-
).text)
|
|
2245
|
-
), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "row" }, /* @__PURE__ */ React6.createElement(Text6, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "Done (", summary.join(" \xB7 "), ")")));
|
|
2246
|
-
},
|
|
2247
|
-
renderResultForAssistant(output) {
|
|
2248
|
-
if (output.status === "async_launched")
|
|
2249
|
-
return asyncLaunchMessage(output.agentId);
|
|
2250
|
-
return output.content.map((b) => b.text).join("\n");
|
|
2251
|
-
},
|
|
2252
|
-
async *call(input, toolUseContext) {
|
|
2253
|
-
const startTime = Date.now();
|
|
2254
|
-
const {
|
|
2255
|
-
abortController,
|
|
2256
|
-
toolUseId,
|
|
2257
|
-
options: {
|
|
2258
|
-
safeMode = false,
|
|
2259
|
-
forkNumber,
|
|
2260
|
-
messageLogName,
|
|
2261
|
-
verbose,
|
|
2262
|
-
model: parentModel,
|
|
2263
|
-
mcpClients
|
|
2264
|
-
},
|
|
2265
|
-
readFileTimestamps
|
|
2266
|
-
} = toolUseContext;
|
|
2267
|
-
const queryFn = typeof toolUseContext?.__testQuery === "function" ? toolUseContext.__testQuery : query;
|
|
2268
|
-
const agentConfig = await getAgentByType(input.subagent_type);
|
|
2269
|
-
if (!agentConfig) {
|
|
2270
|
-
const available = await getAvailableAgentTypes();
|
|
2271
|
-
throw Error(
|
|
2272
|
-
`Agent type '${input.subagent_type}' not found. Available agents: ${available.join(", ")}`
|
|
2273
|
-
);
|
|
2274
|
-
}
|
|
2275
|
-
const effectivePrompt = input.prompt;
|
|
2276
|
-
const normalizedAgentModel = normalizeAgentModelName(agentConfig.model);
|
|
2277
|
-
const defaultSubagentModel = "task";
|
|
2278
|
-
const envSubagentModel = process.env.KODE_SUBAGENT_MODEL ?? process.env.CLAUDE_CODE_SUBAGENT_MODEL;
|
|
2279
|
-
const modelToUse = (typeof envSubagentModel === "string" && envSubagentModel.trim() ? envSubagentModel.trim() : void 0) || modelEnumToPointer(input.model) || (normalizedAgentModel === "inherit" ? parentModel || defaultSubagentModel : normalizedAgentModel) || defaultSubagentModel;
|
|
2280
|
-
const toolFilter = agentConfig.tools;
|
|
2281
|
-
let tools = await getTaskTools(safeMode);
|
|
2282
|
-
if (toolFilter) {
|
|
2283
|
-
const isAllArray = Array.isArray(toolFilter) && toolFilter.length === 1 && toolFilter[0] === "*";
|
|
2284
|
-
if (toolFilter === "*" || isAllArray) {
|
|
2285
|
-
} else if (Array.isArray(toolFilter)) {
|
|
2286
|
-
const allowedToolNames = new Set(
|
|
2287
|
-
toolFilter.map(getToolNameFromSpec).filter(Boolean)
|
|
2288
|
-
);
|
|
2289
|
-
tools = tools.filter((t) => allowedToolNames.has(t.name));
|
|
2290
|
-
}
|
|
2291
|
-
}
|
|
2292
|
-
const disallowedTools = Array.isArray(agentConfig.disallowedTools) ? agentConfig.disallowedTools : [];
|
|
2293
|
-
if (disallowedTools.length > 0) {
|
|
2294
|
-
const disallowedToolNames = new Set(
|
|
2295
|
-
disallowedTools.map(getToolNameFromSpec).filter(Boolean)
|
|
2296
|
-
);
|
|
2297
|
-
tools = tools.filter((t) => !disallowedToolNames.has(t.name));
|
|
2298
|
-
}
|
|
2299
|
-
const agentId = input.resume || generateAgentId();
|
|
2300
|
-
const baseTranscript = input.resume ? getAgentTranscript(input.resume)?.filter((m) => m.type !== "progress") ?? null : [];
|
|
2301
|
-
if (input.resume && baseTranscript === null) {
|
|
2302
|
-
throw Error(`No transcript found for agent ID: ${input.resume}`);
|
|
2303
|
-
}
|
|
2304
|
-
const { forkContextMessages, promptMessages } = buildForkContextForAgent({
|
|
2305
|
-
enabled: agentConfig.forkContext === true,
|
|
2306
|
-
prompt: effectivePrompt,
|
|
2307
|
-
toolUseId,
|
|
2308
|
-
messageLogName,
|
|
2309
|
-
forkNumber
|
|
2310
|
-
});
|
|
2311
|
-
const transcriptMessages = [
|
|
2312
|
-
...baseTranscript || [],
|
|
2313
|
-
...promptMessages
|
|
2314
|
-
];
|
|
2315
|
-
const messagesForQuery = [
|
|
2316
|
-
...forkContextMessages,
|
|
2317
|
-
...transcriptMessages
|
|
2318
|
-
];
|
|
2319
|
-
const [baseSystemPrompt, context, maxThinkingTokens] = await Promise.all([
|
|
2320
|
-
getAgentPrompt(),
|
|
2321
|
-
getContext(),
|
|
2322
|
-
getMaxThinkingTokens(messagesForQuery)
|
|
2323
|
-
]);
|
|
2324
|
-
const systemPrompt = agentConfig.systemPrompt && agentConfig.systemPrompt.length > 0 ? [...baseSystemPrompt, agentConfig.systemPrompt] : baseSystemPrompt;
|
|
2325
|
-
const agentPermissionMode = normalizeAgentPermissionMode(
|
|
2326
|
-
agentConfig.permissionMode
|
|
2327
|
-
);
|
|
2328
|
-
const toolPermissionContext = applyAgentPermissionMode(
|
|
2329
|
-
toolUseContext.options?.toolPermissionContext,
|
|
2330
|
-
{ agentPermissionMode, safeMode }
|
|
2331
|
-
);
|
|
2332
|
-
const queryOptions = {
|
|
2333
|
-
safeMode,
|
|
2334
|
-
forkNumber,
|
|
2335
|
-
messageLogName,
|
|
2336
|
-
tools,
|
|
2337
|
-
commands: [],
|
|
2338
|
-
verbose,
|
|
2339
|
-
permissionMode: "dontAsk",
|
|
2340
|
-
toolPermissionContext,
|
|
2341
|
-
maxThinkingTokens,
|
|
2342
|
-
model: modelToUse,
|
|
2343
|
-
mcpClients
|
|
2344
|
-
};
|
|
2345
|
-
if (input.run_in_background) {
|
|
2346
|
-
const bgAbortController = new AbortController();
|
|
2347
|
-
const taskRecord = {
|
|
2348
|
-
type: "async_agent",
|
|
2349
|
-
agentId,
|
|
2350
|
-
description: input.description,
|
|
2351
|
-
prompt: effectivePrompt,
|
|
2352
|
-
status: "running",
|
|
2353
|
-
startedAt: Date.now(),
|
|
2354
|
-
messages: [...transcriptMessages],
|
|
2355
|
-
abortController: bgAbortController,
|
|
2356
|
-
done: Promise.resolve()
|
|
2357
|
-
};
|
|
2358
|
-
taskRecord.done = (async () => {
|
|
2359
|
-
try {
|
|
2360
|
-
const bgMessages = [...messagesForQuery];
|
|
2361
|
-
const bgTranscriptMessages = [...transcriptMessages];
|
|
2362
|
-
for await (const msg of queryFn(
|
|
2363
|
-
bgMessages,
|
|
2364
|
-
systemPrompt,
|
|
2365
|
-
context,
|
|
2366
|
-
hasPermissionsToUseTool,
|
|
2367
|
-
{
|
|
2368
|
-
abortController: bgAbortController,
|
|
2369
|
-
options: queryOptions,
|
|
2370
|
-
messageId: getLastAssistantMessageId(bgMessages),
|
|
2371
|
-
agentId,
|
|
2372
|
-
readFileTimestamps,
|
|
2373
|
-
setToolJSX: () => {
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
)) {
|
|
2377
|
-
bgMessages.push(msg);
|
|
2378
|
-
bgTranscriptMessages.push(msg);
|
|
2379
|
-
taskRecord.messages = [...bgTranscriptMessages];
|
|
2380
|
-
upsertBackgroundAgentTask(taskRecord);
|
|
2381
|
-
}
|
|
2382
|
-
const lastAssistant2 = last(
|
|
2383
|
-
bgTranscriptMessages.filter((m) => m.type === "assistant")
|
|
2384
|
-
);
|
|
2385
|
-
const content2 = lastAssistant2?.message?.content?.filter(
|
|
2386
|
-
(b) => b.type === "text"
|
|
2387
|
-
);
|
|
2388
|
-
taskRecord.status = "completed";
|
|
2389
|
-
taskRecord.completedAt = Date.now();
|
|
2390
|
-
taskRecord.resultText = (content2 || []).map((b) => b.text).join("\n");
|
|
2391
|
-
taskRecord.messages = [...bgTranscriptMessages];
|
|
2392
|
-
upsertBackgroundAgentTask(taskRecord);
|
|
2393
|
-
saveAgentTranscript(agentId, bgTranscriptMessages);
|
|
2394
|
-
} catch (e) {
|
|
2395
|
-
taskRecord.status = "failed";
|
|
2396
|
-
taskRecord.completedAt = Date.now();
|
|
2397
|
-
taskRecord.error = e instanceof Error ? e.message : String(e);
|
|
2398
|
-
upsertBackgroundAgentTask(taskRecord);
|
|
2399
|
-
}
|
|
2400
|
-
})();
|
|
2401
|
-
upsertBackgroundAgentTask(taskRecord);
|
|
2402
|
-
const output2 = {
|
|
2403
|
-
status: "async_launched",
|
|
2404
|
-
agentId,
|
|
2405
|
-
description: input.description,
|
|
2406
|
-
prompt: effectivePrompt
|
|
2407
|
-
};
|
|
2408
|
-
yield {
|
|
2409
|
-
type: "result",
|
|
2410
|
-
data: output2,
|
|
2411
|
-
resultForAssistant: asyncLaunchMessage(agentId)
|
|
2412
|
-
};
|
|
2413
|
-
return;
|
|
2414
|
-
}
|
|
2415
|
-
const getSidechainNumber = memoize(
|
|
2416
|
-
() => getNextAvailableLogSidechainNumber(messageLogName, forkNumber)
|
|
2417
|
-
);
|
|
2418
|
-
const PROGRESS_THROTTLE_MS = 200;
|
|
2419
|
-
const MAX_RECENT_ACTIONS = 6;
|
|
2420
|
-
let lastProgressEmitAt = 0;
|
|
2421
|
-
let lastEmittedToolUseCount = 0;
|
|
2422
|
-
const recentActions = [];
|
|
2423
|
-
const addRecentAction = (action) => {
|
|
2424
|
-
const trimmed = action.trim();
|
|
2425
|
-
if (!trimmed) return;
|
|
2426
|
-
recentActions.push(trimmed);
|
|
2427
|
-
if (recentActions.length > MAX_RECENT_ACTIONS) {
|
|
2428
|
-
recentActions.splice(0, recentActions.length - MAX_RECENT_ACTIONS);
|
|
2429
|
-
}
|
|
2430
|
-
};
|
|
2431
|
-
const truncate = (text, maxLen) => {
|
|
2432
|
-
const normalized = text.replace(/\s+/g, " ").trim();
|
|
2433
|
-
if (normalized.length <= maxLen) return normalized;
|
|
2434
|
-
return `${normalized.slice(0, maxLen - 1)}\u2026`;
|
|
2435
|
-
};
|
|
2436
|
-
const summarizeToolUse = (name, rawInput) => {
|
|
2437
|
-
const input2 = rawInput && typeof rawInput === "object" ? rawInput : {};
|
|
2438
|
-
switch (name) {
|
|
2439
|
-
case "Read": {
|
|
2440
|
-
const filePath = typeof input2.file_path === "string" && input2.file_path || typeof input2.path === "string" && input2.path || "";
|
|
2441
|
-
return filePath ? `Read ${filePath}` : "Read";
|
|
2442
|
-
}
|
|
2443
|
-
case "Write": {
|
|
2444
|
-
const filePath = typeof input2.file_path === "string" && input2.file_path || typeof input2.path === "string" && input2.path || "";
|
|
2445
|
-
return filePath ? `Write ${filePath}` : "Write";
|
|
2446
|
-
}
|
|
2447
|
-
case "Edit":
|
|
2448
|
-
case "MultiEdit": {
|
|
2449
|
-
const filePath = typeof input2.file_path === "string" && input2.file_path || typeof input2.path === "string" && input2.path || "";
|
|
2450
|
-
return filePath ? `${name} ${filePath}` : name;
|
|
2451
|
-
}
|
|
2452
|
-
case "Grep": {
|
|
2453
|
-
const pattern = typeof input2.pattern === "string" ? input2.pattern : "";
|
|
2454
|
-
return pattern ? `Grep ${truncate(pattern, 80)}` : "Grep";
|
|
2455
|
-
}
|
|
2456
|
-
case "Glob": {
|
|
2457
|
-
const pattern = typeof input2.pattern === "string" && input2.pattern || typeof input2.glob === "string" && input2.glob || "";
|
|
2458
|
-
return pattern ? `Glob ${truncate(pattern, 80)}` : "Glob";
|
|
2459
|
-
}
|
|
2460
|
-
case "Bash": {
|
|
2461
|
-
const command = typeof input2.command === "string" ? input2.command : "";
|
|
2462
|
-
return command ? `Bash ${truncate(command, 80)}` : "Bash";
|
|
2463
|
-
}
|
|
2464
|
-
case "WebFetch":
|
|
2465
|
-
case "WebSearch": {
|
|
2466
|
-
const url = typeof input2.url === "string" ? input2.url : "";
|
|
2467
|
-
const query2 = typeof input2.query === "string" ? input2.query : "";
|
|
2468
|
-
if (url) return `${name} ${truncate(url, 100)}`;
|
|
2469
|
-
if (query2) return `${name} ${truncate(query2, 100)}`;
|
|
2470
|
-
return name;
|
|
2471
|
-
}
|
|
2472
|
-
default:
|
|
2473
|
-
return name;
|
|
2474
|
-
}
|
|
2475
|
-
};
|
|
2476
|
-
const renderProgressText = (toolUseCount2) => {
|
|
2477
|
-
const header = `${input.description || "Task"}\u2026 (${toolUseCount2} tool${toolUseCount2 === 1 ? "" : "s"})`;
|
|
2478
|
-
if (recentActions.length === 0) return header;
|
|
2479
|
-
const lines = recentActions.map((a) => `- ${a}`);
|
|
2480
|
-
return [header, ...lines].join("\n");
|
|
2481
|
-
};
|
|
2482
|
-
yield {
|
|
2483
|
-
type: "progress",
|
|
2484
|
-
content: createAssistantMessage(
|
|
2485
|
-
`<tool-progress>${renderProgressText(0)}</tool-progress>`
|
|
2486
|
-
)
|
|
2487
|
-
};
|
|
2488
|
-
lastProgressEmitAt = Date.now();
|
|
2489
|
-
let toolUseCount = 0;
|
|
2490
|
-
for await (const message of queryFn(
|
|
2491
|
-
messagesForQuery,
|
|
2492
|
-
systemPrompt,
|
|
2493
|
-
context,
|
|
2494
|
-
hasPermissionsToUseTool,
|
|
2495
|
-
{
|
|
2496
|
-
abortController,
|
|
2497
|
-
options: queryOptions,
|
|
2498
|
-
messageId: getLastAssistantMessageId(messagesForQuery),
|
|
2499
|
-
agentId,
|
|
2500
|
-
readFileTimestamps,
|
|
2501
|
-
setToolJSX: () => {
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
)) {
|
|
2505
|
-
messagesForQuery.push(message);
|
|
2506
|
-
transcriptMessages.push(message);
|
|
2507
|
-
overwriteLog(
|
|
2508
|
-
getMessagesPath(messageLogName, forkNumber, getSidechainNumber()),
|
|
2509
|
-
transcriptMessages.filter((_) => _.type !== "progress"),
|
|
2510
|
-
{ conversationKey: `${messageLogName}:${forkNumber}` }
|
|
2511
|
-
);
|
|
2512
|
-
if (message.type === "assistant") {
|
|
2513
|
-
for (const block of message.message.content) {
|
|
2514
|
-
if (block.type === "tool_use" || block.type === "server_tool_use" || block.type === "mcp_tool_use") {
|
|
2515
|
-
toolUseCount += 1;
|
|
2516
|
-
addRecentAction(summarizeToolUse(block.name, block.input));
|
|
2517
|
-
}
|
|
2518
|
-
}
|
|
2519
|
-
}
|
|
2520
|
-
const now = Date.now();
|
|
2521
|
-
const hasNewToolUses = toolUseCount > lastEmittedToolUseCount;
|
|
2522
|
-
const shouldEmit = hasNewToolUses && (lastEmittedToolUseCount === 0 || now - lastProgressEmitAt >= PROGRESS_THROTTLE_MS);
|
|
2523
|
-
if (shouldEmit) {
|
|
2524
|
-
yield {
|
|
2525
|
-
type: "progress",
|
|
2526
|
-
content: createAssistantMessage(
|
|
2527
|
-
`<tool-progress>${renderProgressText(toolUseCount)}</tool-progress>`
|
|
2528
|
-
)
|
|
2529
|
-
};
|
|
2530
|
-
lastEmittedToolUseCount = toolUseCount;
|
|
2531
|
-
lastProgressEmitAt = now;
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
const lastAssistant = last(
|
|
2535
|
-
transcriptMessages.filter((m) => m.type === "assistant")
|
|
2536
|
-
);
|
|
2537
|
-
if (!lastAssistant || lastAssistant.type !== "assistant") {
|
|
2538
|
-
throw Error("No assistant messages found");
|
|
2539
|
-
}
|
|
2540
|
-
const content = lastAssistant.message.content.filter(
|
|
2541
|
-
(b) => b.type === "text"
|
|
2542
|
-
);
|
|
2543
|
-
saveAgentTranscript(agentId, transcriptMessages);
|
|
2544
|
-
const totalDurationMs = Date.now() - startTime;
|
|
2545
|
-
const totalTokens = countTokens(transcriptMessages);
|
|
2546
|
-
const usage = lastAssistant.message.usage;
|
|
2547
|
-
const output = {
|
|
2548
|
-
status: "completed",
|
|
2549
|
-
agentId,
|
|
2550
|
-
prompt: effectivePrompt,
|
|
2551
|
-
content,
|
|
2552
|
-
totalToolUseCount: toolUseCount,
|
|
2553
|
-
totalDurationMs,
|
|
2554
|
-
totalTokens,
|
|
2555
|
-
usage
|
|
2556
|
-
};
|
|
2557
|
-
const agentIdBlock = {
|
|
2558
|
-
type: "text",
|
|
2559
|
-
text: `agentId: ${agentId} (for resuming to continue this agent's work if needed)`,
|
|
2560
|
-
citations: []
|
|
2561
|
-
};
|
|
2562
|
-
yield {
|
|
2563
|
-
type: "result",
|
|
2564
|
-
data: output,
|
|
2565
|
-
resultForAssistant: [...content, agentIdBlock]
|
|
2566
|
-
};
|
|
2567
|
-
}
|
|
2568
|
-
};
|
|
2569
|
-
|
|
2570
|
-
// src/tools/index.ts
|
|
2571
|
-
var getAllTools = () => [
|
|
2572
|
-
TaskTool,
|
|
2573
|
-
AskExpertModelTool,
|
|
2574
|
-
BashTool,
|
|
2575
|
-
TaskOutputTool,
|
|
2576
|
-
KillShellTool,
|
|
2577
|
-
GlobTool,
|
|
2578
|
-
GrepTool,
|
|
2579
|
-
LspTool,
|
|
2580
|
-
FileReadTool,
|
|
2581
|
-
FileEditTool,
|
|
2582
|
-
FileWriteTool,
|
|
2583
|
-
NotebookEditTool,
|
|
2584
|
-
TodoWriteTool,
|
|
2585
|
-
WebSearchTool,
|
|
2586
|
-
WebFetchTool,
|
|
2587
|
-
AskUserQuestionTool,
|
|
2588
|
-
EnterPlanModeTool,
|
|
2589
|
-
ExitPlanModeTool,
|
|
2590
|
-
SlashCommandTool,
|
|
2591
|
-
SkillTool,
|
|
2592
|
-
ListMcpResourcesTool,
|
|
2593
|
-
ReadMcpResourceTool,
|
|
2594
|
-
MCPTool
|
|
2595
|
-
];
|
|
2596
|
-
var getTools = memoize2(
|
|
2597
|
-
async (_includeOptional) => {
|
|
2598
|
-
const tools = [...getAllTools(), ...await getMCPTools()];
|
|
2599
|
-
const isEnabled = await Promise.all(tools.map((tool) => tool.isEnabled()));
|
|
2600
|
-
return tools.filter((_, i) => isEnabled[i]);
|
|
2601
|
-
}
|
|
2602
|
-
);
|
|
2603
|
-
var getReadOnlyTools = memoize2(async () => {
|
|
2604
|
-
const tools = getAllTools().filter((tool) => tool.isReadOnly());
|
|
2605
|
-
const isEnabled = await Promise.all(tools.map((tool) => tool.isEnabled()));
|
|
2606
|
-
return tools.filter((_, index) => isEnabled[index]);
|
|
2607
|
-
});
|
|
2608
|
-
|
|
2609
|
-
export {
|
|
2610
|
-
getAllTools,
|
|
2611
|
-
getTools,
|
|
2612
|
-
getReadOnlyTools
|
|
2613
|
-
};
|