@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-YXYYDIMI.js
DELETED
|
@@ -1,2931 +0,0 @@
|
|
|
1
|
-
import { createRequire as __kodeCreateRequire } from "node:module";
|
|
2
|
-
const require = __kodeCreateRequire(import.meta.url);
|
|
3
|
-
import {
|
|
4
|
-
MACRO
|
|
5
|
-
} from "./chunk-F2SJXUDI.js";
|
|
6
|
-
|
|
7
|
-
// src/utils/state/index.ts
|
|
8
|
-
import { cwd } from "process";
|
|
9
|
-
|
|
10
|
-
// src/utils/bun/shell.ts
|
|
11
|
-
import { spawn } from "child_process";
|
|
12
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync4, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
|
|
13
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
14
|
-
import { homedir as homedir2 } from "os";
|
|
15
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
16
|
-
import which from "which";
|
|
17
|
-
|
|
18
|
-
// src/utils/log/index.ts
|
|
19
|
-
import {
|
|
20
|
-
existsSync as existsSync2,
|
|
21
|
-
mkdirSync as mkdirSync2,
|
|
22
|
-
writeFileSync,
|
|
23
|
-
readFileSync as readFileSync2,
|
|
24
|
-
readdirSync,
|
|
25
|
-
statSync,
|
|
26
|
-
copyFileSync,
|
|
27
|
-
promises as fsPromises
|
|
28
|
-
} from "fs";
|
|
29
|
-
import { dirname, join as join3 } from "path";
|
|
30
|
-
|
|
31
|
-
// src/services/telemetry/sentry.ts
|
|
32
|
-
function initSentry() {
|
|
33
|
-
}
|
|
34
|
-
async function captureException(error) {
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// src/utils/log/index.ts
|
|
38
|
-
import { randomUUID } from "crypto";
|
|
39
|
-
import envPaths from "env-paths";
|
|
40
|
-
|
|
41
|
-
// src/constants/product.ts
|
|
42
|
-
var PRODUCT_NAME = "Kode";
|
|
43
|
-
var PROJECT_FILE = "AGENTS.md";
|
|
44
|
-
var PRODUCT_COMMAND = "kode";
|
|
45
|
-
var CONFIG_BASE_DIR = ".kode";
|
|
46
|
-
var CONFIG_FILE = ".kode.json";
|
|
47
|
-
var GITHUB_ISSUES_REPO_URL = "https://github.com/shareAI-lab/Anykode/issues";
|
|
48
|
-
var ASCII_LOGO = `
|
|
49
|
-
_ _ _ __ _
|
|
50
|
-
| | __ _ ___ | |_ | |/ / ___ __| | ___
|
|
51
|
-
| | / _\` | / __| | __| | ' / / _ \\ / _\` | / _ \\
|
|
52
|
-
| |___ | (_| | \\__ \\ | |_ | . \\ | (_) | | (_| | | __/
|
|
53
|
-
|_____| \\__,_| |___/ \\__| |_|\\_\\ \\___/ \\__,_| \\___|
|
|
54
|
-
|
|
55
|
-
`;
|
|
56
|
-
|
|
57
|
-
// src/utils/plan/planMode.ts
|
|
58
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync } from "fs";
|
|
59
|
-
import { randomBytes } from "crypto";
|
|
60
|
-
import { isAbsolute, join as join2, relative, resolve, parse } from "path";
|
|
61
|
-
|
|
62
|
-
// src/utils/system/execFileNoThrow.ts
|
|
63
|
-
import { execFile } from "child_process";
|
|
64
|
-
var MS_IN_SECOND = 1e3;
|
|
65
|
-
var SECONDS_IN_MINUTE = 60;
|
|
66
|
-
function execFileNoThrow(file, args, abortSignal, timeout = 10 * SECONDS_IN_MINUTE * MS_IN_SECOND, preserveOutputOnError = true) {
|
|
67
|
-
return new Promise((resolve3) => {
|
|
68
|
-
try {
|
|
69
|
-
execFile(
|
|
70
|
-
file,
|
|
71
|
-
args,
|
|
72
|
-
{
|
|
73
|
-
maxBuffer: 1e6,
|
|
74
|
-
signal: abortSignal,
|
|
75
|
-
timeout,
|
|
76
|
-
cwd: getCwd()
|
|
77
|
-
},
|
|
78
|
-
(error, stdout, stderr) => {
|
|
79
|
-
if (error) {
|
|
80
|
-
if (preserveOutputOnError) {
|
|
81
|
-
const errorCode = typeof error.code === "number" ? error.code : 1;
|
|
82
|
-
resolve3({
|
|
83
|
-
stdout: stdout || "",
|
|
84
|
-
stderr: stderr || "",
|
|
85
|
-
code: errorCode
|
|
86
|
-
});
|
|
87
|
-
} else {
|
|
88
|
-
resolve3({ stdout: "", stderr: "", code: 1 });
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
resolve3({ stdout, stderr, code: 0 });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
} catch (error) {
|
|
96
|
-
logError(error);
|
|
97
|
-
resolve3({ stdout: "", stderr: "", code: 1 });
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// src/utils/config/env.ts
|
|
103
|
-
import { memoize } from "lodash-es";
|
|
104
|
-
import { join } from "path";
|
|
105
|
-
import { homedir } from "os";
|
|
106
|
-
function getKodeBaseDir() {
|
|
107
|
-
return process.env.KODE_CONFIG_DIR ?? process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), CONFIG_BASE_DIR);
|
|
108
|
-
}
|
|
109
|
-
function getGlobalConfigFilePath() {
|
|
110
|
-
return process.env.KODE_CONFIG_DIR || process.env.CLAUDE_CONFIG_DIR ? join(getKodeBaseDir(), "config.json") : join(homedir(), CONFIG_FILE);
|
|
111
|
-
}
|
|
112
|
-
function getMemoryDir() {
|
|
113
|
-
return join(getKodeBaseDir(), "memory");
|
|
114
|
-
}
|
|
115
|
-
var KODE_BASE_DIR = getKodeBaseDir();
|
|
116
|
-
var GLOBAL_CONFIG_FILE = getGlobalConfigFilePath();
|
|
117
|
-
var MEMORY_DIR = getMemoryDir();
|
|
118
|
-
var getIsDocker = memoize(async () => {
|
|
119
|
-
const { code } = await execFileNoThrow("test", ["-f", "/.dockerenv"]);
|
|
120
|
-
if (code !== 0) {
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
return process.platform === "linux";
|
|
124
|
-
});
|
|
125
|
-
var hasInternetAccess = memoize(async () => {
|
|
126
|
-
const offline = process.env.KODE_OFFLINE ?? process.env.OFFLINE ?? process.env.NO_NETWORK ?? "";
|
|
127
|
-
const normalized = String(offline).trim().toLowerCase();
|
|
128
|
-
if (["1", "true", "yes", "on"].includes(normalized)) return false;
|
|
129
|
-
return true;
|
|
130
|
-
});
|
|
131
|
-
var env = {
|
|
132
|
-
getIsDocker,
|
|
133
|
-
hasInternetAccess,
|
|
134
|
-
isCI: Boolean(process.env.CI),
|
|
135
|
-
platform: process.platform === "win32" ? "windows" : process.platform === "darwin" ? "macos" : "linux",
|
|
136
|
-
nodeVersion: process.version,
|
|
137
|
-
terminal: process.env.TERM_PROGRAM
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// src/utils/plan/planSlugWords.ts
|
|
141
|
-
var PLAN_SLUG_ADJECTIVES = [
|
|
142
|
-
"abundant",
|
|
143
|
-
"ancient",
|
|
144
|
-
"bright",
|
|
145
|
-
"calm",
|
|
146
|
-
"cheerful",
|
|
147
|
-
"clever",
|
|
148
|
-
"cozy",
|
|
149
|
-
"curious",
|
|
150
|
-
"dapper",
|
|
151
|
-
"dazzling",
|
|
152
|
-
"deep",
|
|
153
|
-
"delightful",
|
|
154
|
-
"eager",
|
|
155
|
-
"elegant",
|
|
156
|
-
"enchanted",
|
|
157
|
-
"fancy",
|
|
158
|
-
"fluffy",
|
|
159
|
-
"gentle",
|
|
160
|
-
"gleaming",
|
|
161
|
-
"golden",
|
|
162
|
-
"graceful",
|
|
163
|
-
"happy",
|
|
164
|
-
"hidden",
|
|
165
|
-
"humble",
|
|
166
|
-
"jolly",
|
|
167
|
-
"joyful",
|
|
168
|
-
"keen",
|
|
169
|
-
"kind",
|
|
170
|
-
"lively",
|
|
171
|
-
"lovely",
|
|
172
|
-
"lucky",
|
|
173
|
-
"luminous",
|
|
174
|
-
"magical",
|
|
175
|
-
"majestic",
|
|
176
|
-
"mellow",
|
|
177
|
-
"merry",
|
|
178
|
-
"mighty",
|
|
179
|
-
"misty",
|
|
180
|
-
"noble",
|
|
181
|
-
"peaceful",
|
|
182
|
-
"playful",
|
|
183
|
-
"polished",
|
|
184
|
-
"precious",
|
|
185
|
-
"proud",
|
|
186
|
-
"quiet",
|
|
187
|
-
"quirky",
|
|
188
|
-
"radiant",
|
|
189
|
-
"rosy",
|
|
190
|
-
"serene",
|
|
191
|
-
"shiny",
|
|
192
|
-
"silly",
|
|
193
|
-
"sleepy",
|
|
194
|
-
"smooth",
|
|
195
|
-
"snazzy",
|
|
196
|
-
"snug",
|
|
197
|
-
"snuggly",
|
|
198
|
-
"soft",
|
|
199
|
-
"sparkling",
|
|
200
|
-
"spicy",
|
|
201
|
-
"splendid",
|
|
202
|
-
"sprightly",
|
|
203
|
-
"starry",
|
|
204
|
-
"steady",
|
|
205
|
-
"sunny",
|
|
206
|
-
"swift",
|
|
207
|
-
"tender",
|
|
208
|
-
"tidy",
|
|
209
|
-
"toasty",
|
|
210
|
-
"tranquil",
|
|
211
|
-
"twinkly",
|
|
212
|
-
"valiant",
|
|
213
|
-
"vast",
|
|
214
|
-
"velvet",
|
|
215
|
-
"vivid",
|
|
216
|
-
"warm",
|
|
217
|
-
"whimsical",
|
|
218
|
-
"wild",
|
|
219
|
-
"wise",
|
|
220
|
-
"witty",
|
|
221
|
-
"wondrous",
|
|
222
|
-
"zany",
|
|
223
|
-
"zesty",
|
|
224
|
-
"zippy",
|
|
225
|
-
"breezy",
|
|
226
|
-
"bubbly",
|
|
227
|
-
"buzzing",
|
|
228
|
-
"cheeky",
|
|
229
|
-
"cosmic",
|
|
230
|
-
"cozy",
|
|
231
|
-
"crispy",
|
|
232
|
-
"crystalline",
|
|
233
|
-
"cuddly",
|
|
234
|
-
"drifting",
|
|
235
|
-
"dreamy",
|
|
236
|
-
"effervescent",
|
|
237
|
-
"ethereal",
|
|
238
|
-
"fizzy",
|
|
239
|
-
"flickering",
|
|
240
|
-
"floating",
|
|
241
|
-
"floofy",
|
|
242
|
-
"fluttering",
|
|
243
|
-
"foamy",
|
|
244
|
-
"frolicking",
|
|
245
|
-
"fuzzy",
|
|
246
|
-
"giggly",
|
|
247
|
-
"glimmering",
|
|
248
|
-
"glistening",
|
|
249
|
-
"glittery",
|
|
250
|
-
"glowing",
|
|
251
|
-
"goofy",
|
|
252
|
-
"groovy",
|
|
253
|
-
"harmonic",
|
|
254
|
-
"hazy",
|
|
255
|
-
"humming",
|
|
256
|
-
"iridescent",
|
|
257
|
-
"jaunty",
|
|
258
|
-
"jazzy",
|
|
259
|
-
"jiggly",
|
|
260
|
-
"melodic",
|
|
261
|
-
"moonlit",
|
|
262
|
-
"mossy",
|
|
263
|
-
"nifty",
|
|
264
|
-
"peppy",
|
|
265
|
-
"prancy",
|
|
266
|
-
"purrfect",
|
|
267
|
-
"purring",
|
|
268
|
-
"quizzical",
|
|
269
|
-
"rippling",
|
|
270
|
-
"rustling",
|
|
271
|
-
"shimmering",
|
|
272
|
-
"shimmying",
|
|
273
|
-
"snappy",
|
|
274
|
-
"snoopy",
|
|
275
|
-
"squishy",
|
|
276
|
-
"swirling",
|
|
277
|
-
"ticklish",
|
|
278
|
-
"tingly",
|
|
279
|
-
"twinkling",
|
|
280
|
-
"velvety",
|
|
281
|
-
"wiggly",
|
|
282
|
-
"wobbly",
|
|
283
|
-
"woolly",
|
|
284
|
-
"zazzy",
|
|
285
|
-
"abstract",
|
|
286
|
-
"adaptive",
|
|
287
|
-
"agile",
|
|
288
|
-
"async",
|
|
289
|
-
"atomic",
|
|
290
|
-
"binary",
|
|
291
|
-
"cached",
|
|
292
|
-
"compiled",
|
|
293
|
-
"composed",
|
|
294
|
-
"compressed",
|
|
295
|
-
"concurrent",
|
|
296
|
-
"cryptic",
|
|
297
|
-
"curried",
|
|
298
|
-
"declarative",
|
|
299
|
-
"delegated",
|
|
300
|
-
"distributed",
|
|
301
|
-
"dynamic",
|
|
302
|
-
"eager",
|
|
303
|
-
"elegant",
|
|
304
|
-
"encapsulated",
|
|
305
|
-
"enumerated",
|
|
306
|
-
"eventual",
|
|
307
|
-
"expressive",
|
|
308
|
-
"federated",
|
|
309
|
-
"functional",
|
|
310
|
-
"generic",
|
|
311
|
-
"greedy",
|
|
312
|
-
"hashed",
|
|
313
|
-
"idempotent",
|
|
314
|
-
"immutable",
|
|
315
|
-
"imperative",
|
|
316
|
-
"indexed",
|
|
317
|
-
"inherited",
|
|
318
|
-
"iterative",
|
|
319
|
-
"lazy",
|
|
320
|
-
"lexical",
|
|
321
|
-
"linear",
|
|
322
|
-
"linked",
|
|
323
|
-
"logical",
|
|
324
|
-
"memoized",
|
|
325
|
-
"modular",
|
|
326
|
-
"mutable",
|
|
327
|
-
"nested",
|
|
328
|
-
"optimized",
|
|
329
|
-
"parallel",
|
|
330
|
-
"parsed",
|
|
331
|
-
"partitioned",
|
|
332
|
-
"piped",
|
|
333
|
-
"polymorphic",
|
|
334
|
-
"pure",
|
|
335
|
-
"reactive",
|
|
336
|
-
"recursive",
|
|
337
|
-
"refactored",
|
|
338
|
-
"reflective",
|
|
339
|
-
"replicated",
|
|
340
|
-
"resilient",
|
|
341
|
-
"robust",
|
|
342
|
-
"scalable",
|
|
343
|
-
"sequential",
|
|
344
|
-
"serialized",
|
|
345
|
-
"sharded",
|
|
346
|
-
"sorted",
|
|
347
|
-
"staged",
|
|
348
|
-
"stateful",
|
|
349
|
-
"stateless",
|
|
350
|
-
"streamed",
|
|
351
|
-
"structured",
|
|
352
|
-
"synchronous",
|
|
353
|
-
"synthetic",
|
|
354
|
-
"temporal",
|
|
355
|
-
"transient",
|
|
356
|
-
"typed",
|
|
357
|
-
"unified",
|
|
358
|
-
"validated",
|
|
359
|
-
"vectorized",
|
|
360
|
-
"virtual"
|
|
361
|
-
];
|
|
362
|
-
var PLAN_SLUG_VERBS = [
|
|
363
|
-
"baking",
|
|
364
|
-
"beaming",
|
|
365
|
-
"booping",
|
|
366
|
-
"bouncing",
|
|
367
|
-
"brewing",
|
|
368
|
-
"bubbling",
|
|
369
|
-
"chasing",
|
|
370
|
-
"churning",
|
|
371
|
-
"coalescing",
|
|
372
|
-
"conjuring",
|
|
373
|
-
"cooking",
|
|
374
|
-
"crafting",
|
|
375
|
-
"crunching",
|
|
376
|
-
"cuddling",
|
|
377
|
-
"dancing",
|
|
378
|
-
"dazzling",
|
|
379
|
-
"discovering",
|
|
380
|
-
"doodling",
|
|
381
|
-
"dreaming",
|
|
382
|
-
"drifting",
|
|
383
|
-
"enchanting",
|
|
384
|
-
"exploring",
|
|
385
|
-
"finding",
|
|
386
|
-
"floating",
|
|
387
|
-
"fluttering",
|
|
388
|
-
"foraging",
|
|
389
|
-
"forging",
|
|
390
|
-
"frolicking",
|
|
391
|
-
"gathering",
|
|
392
|
-
"giggling",
|
|
393
|
-
"gliding",
|
|
394
|
-
"greeting",
|
|
395
|
-
"growing",
|
|
396
|
-
"hatching",
|
|
397
|
-
"herding",
|
|
398
|
-
"honking",
|
|
399
|
-
"hopping",
|
|
400
|
-
"hugging",
|
|
401
|
-
"humming",
|
|
402
|
-
"imagining",
|
|
403
|
-
"inventing",
|
|
404
|
-
"jingling",
|
|
405
|
-
"juggling",
|
|
406
|
-
"jumping",
|
|
407
|
-
"kindling",
|
|
408
|
-
"knitting",
|
|
409
|
-
"launching",
|
|
410
|
-
"leaping",
|
|
411
|
-
"mapping",
|
|
412
|
-
"marinating",
|
|
413
|
-
"meandering",
|
|
414
|
-
"mixing",
|
|
415
|
-
"moseying",
|
|
416
|
-
"munching",
|
|
417
|
-
"napping",
|
|
418
|
-
"nibbling",
|
|
419
|
-
"noodling",
|
|
420
|
-
"orbiting",
|
|
421
|
-
"painting",
|
|
422
|
-
"percolating",
|
|
423
|
-
"petting",
|
|
424
|
-
"plotting",
|
|
425
|
-
"pondering",
|
|
426
|
-
"popping",
|
|
427
|
-
"prancing",
|
|
428
|
-
"purring",
|
|
429
|
-
"puzzling",
|
|
430
|
-
"questing",
|
|
431
|
-
"riding",
|
|
432
|
-
"roaming",
|
|
433
|
-
"rolling",
|
|
434
|
-
"sauteeing",
|
|
435
|
-
"scribbling",
|
|
436
|
-
"seeking",
|
|
437
|
-
"shimmying",
|
|
438
|
-
"singing",
|
|
439
|
-
"skipping",
|
|
440
|
-
"sleeping",
|
|
441
|
-
"snacking",
|
|
442
|
-
"sniffing",
|
|
443
|
-
"snuggling",
|
|
444
|
-
"soaring",
|
|
445
|
-
"sparking",
|
|
446
|
-
"spinning",
|
|
447
|
-
"splashing",
|
|
448
|
-
"sprouting",
|
|
449
|
-
"squishing",
|
|
450
|
-
"stargazing",
|
|
451
|
-
"stirring",
|
|
452
|
-
"strolling",
|
|
453
|
-
"swimming",
|
|
454
|
-
"swinging",
|
|
455
|
-
"tickling",
|
|
456
|
-
"tinkering",
|
|
457
|
-
"toasting",
|
|
458
|
-
"tumbling",
|
|
459
|
-
"twirling",
|
|
460
|
-
"waddling",
|
|
461
|
-
"wandering",
|
|
462
|
-
"watching",
|
|
463
|
-
"weaving",
|
|
464
|
-
"whistling",
|
|
465
|
-
"wibbling",
|
|
466
|
-
"wiggling",
|
|
467
|
-
"wishing",
|
|
468
|
-
"wobbling",
|
|
469
|
-
"wondering",
|
|
470
|
-
"yawning",
|
|
471
|
-
"zooming"
|
|
472
|
-
];
|
|
473
|
-
var PLAN_SLUG_NOUNS = [
|
|
474
|
-
"aurora",
|
|
475
|
-
"avalanche",
|
|
476
|
-
"blossom",
|
|
477
|
-
"breeze",
|
|
478
|
-
"brook",
|
|
479
|
-
"bubble",
|
|
480
|
-
"canyon",
|
|
481
|
-
"cascade",
|
|
482
|
-
"cloud",
|
|
483
|
-
"clover",
|
|
484
|
-
"comet",
|
|
485
|
-
"coral",
|
|
486
|
-
"cosmos",
|
|
487
|
-
"creek",
|
|
488
|
-
"crescent",
|
|
489
|
-
"crystal",
|
|
490
|
-
"dawn",
|
|
491
|
-
"dewdrop",
|
|
492
|
-
"dusk",
|
|
493
|
-
"eclipse",
|
|
494
|
-
"ember",
|
|
495
|
-
"feather",
|
|
496
|
-
"fern",
|
|
497
|
-
"firefly",
|
|
498
|
-
"flame",
|
|
499
|
-
"flurry",
|
|
500
|
-
"fog",
|
|
501
|
-
"forest",
|
|
502
|
-
"frost",
|
|
503
|
-
"galaxy",
|
|
504
|
-
"garden",
|
|
505
|
-
"glacier",
|
|
506
|
-
"glade",
|
|
507
|
-
"grove",
|
|
508
|
-
"harbor",
|
|
509
|
-
"horizon",
|
|
510
|
-
"island",
|
|
511
|
-
"lagoon",
|
|
512
|
-
"lake",
|
|
513
|
-
"leaf",
|
|
514
|
-
"lightning",
|
|
515
|
-
"meadow",
|
|
516
|
-
"meteor",
|
|
517
|
-
"mist",
|
|
518
|
-
"moon",
|
|
519
|
-
"moonbeam",
|
|
520
|
-
"mountain",
|
|
521
|
-
"nebula",
|
|
522
|
-
"nova",
|
|
523
|
-
"ocean",
|
|
524
|
-
"orbit",
|
|
525
|
-
"pebble",
|
|
526
|
-
"petal",
|
|
527
|
-
"pine",
|
|
528
|
-
"planet",
|
|
529
|
-
"pond",
|
|
530
|
-
"puddle",
|
|
531
|
-
"quasar",
|
|
532
|
-
"rain",
|
|
533
|
-
"rainbow",
|
|
534
|
-
"reef",
|
|
535
|
-
"ripple",
|
|
536
|
-
"river",
|
|
537
|
-
"shore",
|
|
538
|
-
"sky",
|
|
539
|
-
"snowflake",
|
|
540
|
-
"spark",
|
|
541
|
-
"spring",
|
|
542
|
-
"star",
|
|
543
|
-
"stardust",
|
|
544
|
-
"starlight",
|
|
545
|
-
"storm",
|
|
546
|
-
"stream",
|
|
547
|
-
"summit",
|
|
548
|
-
"sun",
|
|
549
|
-
"sunbeam",
|
|
550
|
-
"sunrise",
|
|
551
|
-
"sunset",
|
|
552
|
-
"thunder",
|
|
553
|
-
"tide",
|
|
554
|
-
"twilight",
|
|
555
|
-
"valley",
|
|
556
|
-
"volcano",
|
|
557
|
-
"waterfall",
|
|
558
|
-
"wave",
|
|
559
|
-
"willow",
|
|
560
|
-
"wind",
|
|
561
|
-
"alpaca",
|
|
562
|
-
"axolotl",
|
|
563
|
-
"badger",
|
|
564
|
-
"bear",
|
|
565
|
-
"beaver",
|
|
566
|
-
"bee",
|
|
567
|
-
"bird",
|
|
568
|
-
"bumblebee",
|
|
569
|
-
"bunny",
|
|
570
|
-
"cat",
|
|
571
|
-
"chipmunk",
|
|
572
|
-
"crab",
|
|
573
|
-
"crane",
|
|
574
|
-
"deer",
|
|
575
|
-
"dolphin",
|
|
576
|
-
"dove",
|
|
577
|
-
"dragon",
|
|
578
|
-
"dragonfly",
|
|
579
|
-
"duckling",
|
|
580
|
-
"eagle",
|
|
581
|
-
"elephant",
|
|
582
|
-
"falcon",
|
|
583
|
-
"finch",
|
|
584
|
-
"flamingo",
|
|
585
|
-
"fox",
|
|
586
|
-
"frog",
|
|
587
|
-
"giraffe",
|
|
588
|
-
"goose",
|
|
589
|
-
"hamster",
|
|
590
|
-
"hare",
|
|
591
|
-
"hedgehog",
|
|
592
|
-
"hippo",
|
|
593
|
-
"hummingbird",
|
|
594
|
-
"jellyfish",
|
|
595
|
-
"kitten",
|
|
596
|
-
"koala",
|
|
597
|
-
"ladybug",
|
|
598
|
-
"lark",
|
|
599
|
-
"lemur",
|
|
600
|
-
"llama",
|
|
601
|
-
"lobster",
|
|
602
|
-
"lynx",
|
|
603
|
-
"manatee",
|
|
604
|
-
"meerkat",
|
|
605
|
-
"moth",
|
|
606
|
-
"narwhal",
|
|
607
|
-
"newt",
|
|
608
|
-
"octopus",
|
|
609
|
-
"otter",
|
|
610
|
-
"owl",
|
|
611
|
-
"panda",
|
|
612
|
-
"parrot",
|
|
613
|
-
"peacock",
|
|
614
|
-
"pelican",
|
|
615
|
-
"penguin",
|
|
616
|
-
"phoenix",
|
|
617
|
-
"piglet",
|
|
618
|
-
"platypus",
|
|
619
|
-
"pony",
|
|
620
|
-
"porcupine",
|
|
621
|
-
"puffin",
|
|
622
|
-
"puppy",
|
|
623
|
-
"quail",
|
|
624
|
-
"quokka",
|
|
625
|
-
"rabbit",
|
|
626
|
-
"raccoon",
|
|
627
|
-
"raven",
|
|
628
|
-
"robin",
|
|
629
|
-
"salamander",
|
|
630
|
-
"seahorse",
|
|
631
|
-
"seal",
|
|
632
|
-
"sloth",
|
|
633
|
-
"snail",
|
|
634
|
-
"sparrow",
|
|
635
|
-
"sphinx",
|
|
636
|
-
"squid",
|
|
637
|
-
"squirrel",
|
|
638
|
-
"starfish",
|
|
639
|
-
"swan",
|
|
640
|
-
"tiger",
|
|
641
|
-
"toucan",
|
|
642
|
-
"turtle",
|
|
643
|
-
"unicorn",
|
|
644
|
-
"walrus",
|
|
645
|
-
"whale",
|
|
646
|
-
"wolf",
|
|
647
|
-
"wombat",
|
|
648
|
-
"wren",
|
|
649
|
-
"yeti",
|
|
650
|
-
"zebra",
|
|
651
|
-
"acorn",
|
|
652
|
-
"anchor",
|
|
653
|
-
"balloon",
|
|
654
|
-
"beacon",
|
|
655
|
-
"biscuit",
|
|
656
|
-
"blanket",
|
|
657
|
-
"bonbon",
|
|
658
|
-
"book",
|
|
659
|
-
"boot",
|
|
660
|
-
"cake",
|
|
661
|
-
"candle",
|
|
662
|
-
"candy",
|
|
663
|
-
"castle",
|
|
664
|
-
"charm",
|
|
665
|
-
"clock",
|
|
666
|
-
"cocoa",
|
|
667
|
-
"cookie",
|
|
668
|
-
"crayon",
|
|
669
|
-
"crown",
|
|
670
|
-
"cupcake",
|
|
671
|
-
"donut",
|
|
672
|
-
"dream",
|
|
673
|
-
"fairy",
|
|
674
|
-
"fiddle",
|
|
675
|
-
"flask",
|
|
676
|
-
"flute",
|
|
677
|
-
"fountain",
|
|
678
|
-
"gadget",
|
|
679
|
-
"gem",
|
|
680
|
-
"gizmo",
|
|
681
|
-
"globe",
|
|
682
|
-
"goblet",
|
|
683
|
-
"hammock",
|
|
684
|
-
"harp",
|
|
685
|
-
"haven",
|
|
686
|
-
"hearth",
|
|
687
|
-
"honey",
|
|
688
|
-
"journal",
|
|
689
|
-
"kazoo",
|
|
690
|
-
"kettle",
|
|
691
|
-
"key",
|
|
692
|
-
"kite",
|
|
693
|
-
"lantern",
|
|
694
|
-
"lemon",
|
|
695
|
-
"lighthouse",
|
|
696
|
-
"locket",
|
|
697
|
-
"lollipop",
|
|
698
|
-
"mango",
|
|
699
|
-
"map",
|
|
700
|
-
"marble",
|
|
701
|
-
"marshmallow",
|
|
702
|
-
"melody",
|
|
703
|
-
"mitten",
|
|
704
|
-
"mochi",
|
|
705
|
-
"muffin",
|
|
706
|
-
"music",
|
|
707
|
-
"nest",
|
|
708
|
-
"noodle",
|
|
709
|
-
"oasis",
|
|
710
|
-
"origami",
|
|
711
|
-
"pancake",
|
|
712
|
-
"parasol",
|
|
713
|
-
"peach",
|
|
714
|
-
"pearl",
|
|
715
|
-
"pebble",
|
|
716
|
-
"pie",
|
|
717
|
-
"pillow",
|
|
718
|
-
"pinwheel",
|
|
719
|
-
"pixel",
|
|
720
|
-
"pizza",
|
|
721
|
-
"plum",
|
|
722
|
-
"popcorn",
|
|
723
|
-
"pretzel",
|
|
724
|
-
"prism",
|
|
725
|
-
"pudding",
|
|
726
|
-
"pumpkin",
|
|
727
|
-
"puzzle",
|
|
728
|
-
"quiche",
|
|
729
|
-
"quill",
|
|
730
|
-
"quilt",
|
|
731
|
-
"riddle",
|
|
732
|
-
"rocket",
|
|
733
|
-
"rose",
|
|
734
|
-
"scone",
|
|
735
|
-
"scroll",
|
|
736
|
-
"shell",
|
|
737
|
-
"sketch",
|
|
738
|
-
"snowglobe",
|
|
739
|
-
"sonnet",
|
|
740
|
-
"sparkle",
|
|
741
|
-
"spindle",
|
|
742
|
-
"sprout",
|
|
743
|
-
"sundae",
|
|
744
|
-
"swing",
|
|
745
|
-
"taco",
|
|
746
|
-
"teacup",
|
|
747
|
-
"teapot",
|
|
748
|
-
"thimble",
|
|
749
|
-
"toast",
|
|
750
|
-
"token",
|
|
751
|
-
"tome",
|
|
752
|
-
"tower",
|
|
753
|
-
"treasure",
|
|
754
|
-
"treehouse",
|
|
755
|
-
"trinket",
|
|
756
|
-
"truffle",
|
|
757
|
-
"tulip",
|
|
758
|
-
"umbrella",
|
|
759
|
-
"waffle",
|
|
760
|
-
"wand",
|
|
761
|
-
"whisper",
|
|
762
|
-
"whistle",
|
|
763
|
-
"widget",
|
|
764
|
-
"wreath",
|
|
765
|
-
"zephyr",
|
|
766
|
-
"abelson",
|
|
767
|
-
"adleman",
|
|
768
|
-
"aho",
|
|
769
|
-
"allen",
|
|
770
|
-
"babbage",
|
|
771
|
-
"bachman",
|
|
772
|
-
"backus",
|
|
773
|
-
"barto",
|
|
774
|
-
"bengio",
|
|
775
|
-
"bentley",
|
|
776
|
-
"blum",
|
|
777
|
-
"boole",
|
|
778
|
-
"brooks",
|
|
779
|
-
"catmull",
|
|
780
|
-
"cerf",
|
|
781
|
-
"cherny",
|
|
782
|
-
"church",
|
|
783
|
-
"clarke",
|
|
784
|
-
"cocke",
|
|
785
|
-
"codd",
|
|
786
|
-
"conway",
|
|
787
|
-
"cook",
|
|
788
|
-
"corbato",
|
|
789
|
-
"cray",
|
|
790
|
-
"curry",
|
|
791
|
-
"dahl",
|
|
792
|
-
"diffie",
|
|
793
|
-
"dijkstra",
|
|
794
|
-
"dongarra",
|
|
795
|
-
"eich",
|
|
796
|
-
"emerson",
|
|
797
|
-
"engelbart",
|
|
798
|
-
"feigenbaum",
|
|
799
|
-
"floyd",
|
|
800
|
-
"gosling",
|
|
801
|
-
"graham",
|
|
802
|
-
"gray",
|
|
803
|
-
"hamming",
|
|
804
|
-
"hanrahan",
|
|
805
|
-
"hartmanis",
|
|
806
|
-
"hejlsberg",
|
|
807
|
-
"hellman",
|
|
808
|
-
"hennessy",
|
|
809
|
-
"hickey",
|
|
810
|
-
"hinton",
|
|
811
|
-
"hoare",
|
|
812
|
-
"hollerith",
|
|
813
|
-
"hopcroft",
|
|
814
|
-
"hopper",
|
|
815
|
-
"iverson",
|
|
816
|
-
"kahan",
|
|
817
|
-
"kahn",
|
|
818
|
-
"karp",
|
|
819
|
-
"kay",
|
|
820
|
-
"kernighan",
|
|
821
|
-
"knuth",
|
|
822
|
-
"kurzweil",
|
|
823
|
-
"lamport",
|
|
824
|
-
"lampson",
|
|
825
|
-
"lecun",
|
|
826
|
-
"lerdorf",
|
|
827
|
-
"liskov",
|
|
828
|
-
"lovelace",
|
|
829
|
-
"matsumoto",
|
|
830
|
-
"mccarthy",
|
|
831
|
-
"metcalfe",
|
|
832
|
-
"micali",
|
|
833
|
-
"milner",
|
|
834
|
-
"minsky",
|
|
835
|
-
"moler",
|
|
836
|
-
"moore",
|
|
837
|
-
"naur",
|
|
838
|
-
"neumann",
|
|
839
|
-
"newell",
|
|
840
|
-
"nygaard",
|
|
841
|
-
"papert",
|
|
842
|
-
"parnas",
|
|
843
|
-
"pascal",
|
|
844
|
-
"patterson",
|
|
845
|
-
"pearl",
|
|
846
|
-
"perlis",
|
|
847
|
-
"pike",
|
|
848
|
-
"pnueli",
|
|
849
|
-
"rabin",
|
|
850
|
-
"reddy",
|
|
851
|
-
"ritchie",
|
|
852
|
-
"rivest",
|
|
853
|
-
"rossum",
|
|
854
|
-
"russell",
|
|
855
|
-
"scott",
|
|
856
|
-
"sedgewick",
|
|
857
|
-
"shamir",
|
|
858
|
-
"shannon",
|
|
859
|
-
"sifakis",
|
|
860
|
-
"simon",
|
|
861
|
-
"stallman",
|
|
862
|
-
"stearns",
|
|
863
|
-
"steele",
|
|
864
|
-
"stonebraker",
|
|
865
|
-
"stroustrup",
|
|
866
|
-
"sutherland",
|
|
867
|
-
"sutton",
|
|
868
|
-
"tarjan",
|
|
869
|
-
"thacker",
|
|
870
|
-
"thompson",
|
|
871
|
-
"torvalds",
|
|
872
|
-
"turing",
|
|
873
|
-
"ullman",
|
|
874
|
-
"valiant",
|
|
875
|
-
"wadler",
|
|
876
|
-
"wall",
|
|
877
|
-
"wigderson",
|
|
878
|
-
"wilkes",
|
|
879
|
-
"wilkinson",
|
|
880
|
-
"wirth",
|
|
881
|
-
"wozniak",
|
|
882
|
-
"yao"
|
|
883
|
-
];
|
|
884
|
-
|
|
885
|
-
// src/utils/plan/planMode.ts
|
|
886
|
-
var DEFAULT_CONVERSATION_KEY = "default";
|
|
887
|
-
var MAX_SLUG_ATTEMPTS = 10;
|
|
888
|
-
var TURNS_BETWEEN_ATTACHMENTS = 5;
|
|
889
|
-
var planModeEnabledByConversationKey = /* @__PURE__ */ new Map();
|
|
890
|
-
var planSlugCache = /* @__PURE__ */ new Map();
|
|
891
|
-
var planModeFlagsByConversationKey = /* @__PURE__ */ new Map();
|
|
892
|
-
var planModeAttachmentStateByAgentKey = /* @__PURE__ */ new Map();
|
|
893
|
-
var activePlanConversationKey = null;
|
|
894
|
-
function getConversationKey(context) {
|
|
895
|
-
const messageLogName = context?.options?.messageLogName ?? DEFAULT_CONVERSATION_KEY;
|
|
896
|
-
const forkNumber = context?.options?.forkNumber ?? 0;
|
|
897
|
-
return `${messageLogName}:${forkNumber}`;
|
|
898
|
-
}
|
|
899
|
-
function getPlanConversationKey(context) {
|
|
900
|
-
return getConversationKey(context);
|
|
901
|
-
}
|
|
902
|
-
function setActivePlanConversationKey(conversationKey) {
|
|
903
|
-
activePlanConversationKey = conversationKey;
|
|
904
|
-
}
|
|
905
|
-
function getAgentKey(context) {
|
|
906
|
-
const conversationKey = getConversationKey(context);
|
|
907
|
-
const agentId = context?.agentId ?? "main";
|
|
908
|
-
return `${conversationKey}:${agentId}`;
|
|
909
|
-
}
|
|
910
|
-
function pickIndex(length) {
|
|
911
|
-
return randomBytes(4).readUInt32BE(0) % length;
|
|
912
|
-
}
|
|
913
|
-
function pickWord(words) {
|
|
914
|
-
return words[pickIndex(words.length)];
|
|
915
|
-
}
|
|
916
|
-
function generateSlug() {
|
|
917
|
-
const adjective = pickWord(PLAN_SLUG_ADJECTIVES);
|
|
918
|
-
const verb = pickWord(PLAN_SLUG_VERBS);
|
|
919
|
-
const noun = pickWord(PLAN_SLUG_NOUNS);
|
|
920
|
-
return `${adjective}-${verb}-${noun}`;
|
|
921
|
-
}
|
|
922
|
-
function getOrCreatePlanSlug(conversationKey) {
|
|
923
|
-
const existing = planSlugCache.get(conversationKey);
|
|
924
|
-
if (existing) return existing;
|
|
925
|
-
const dir = getPlanDirectory();
|
|
926
|
-
let slug = null;
|
|
927
|
-
for (let attempt = 0; attempt < MAX_SLUG_ATTEMPTS; attempt++) {
|
|
928
|
-
slug = generateSlug();
|
|
929
|
-
const path = join2(dir, `${slug}.md`);
|
|
930
|
-
if (!existsSync(path)) break;
|
|
931
|
-
}
|
|
932
|
-
if (!slug) slug = generateSlug();
|
|
933
|
-
planSlugCache.set(conversationKey, slug);
|
|
934
|
-
return slug;
|
|
935
|
-
}
|
|
936
|
-
function extractSlugFromPlanFilePath(planFilePath) {
|
|
937
|
-
if (!planFilePath) return null;
|
|
938
|
-
const baseName = parse(planFilePath).name;
|
|
939
|
-
if (!baseName) return null;
|
|
940
|
-
const agentMarker = "-agent-";
|
|
941
|
-
const idx = baseName.lastIndexOf(agentMarker);
|
|
942
|
-
if (idx === -1) return baseName;
|
|
943
|
-
if (idx === 0) return null;
|
|
944
|
-
return baseName.slice(0, idx);
|
|
945
|
-
}
|
|
946
|
-
function getOrCreatePlanModeFlags(conversationKey) {
|
|
947
|
-
const existing = planModeFlagsByConversationKey.get(conversationKey);
|
|
948
|
-
if (existing) return existing;
|
|
949
|
-
const created = {
|
|
950
|
-
hasExitedPlanMode: false,
|
|
951
|
-
needsPlanModeExitAttachment: false
|
|
952
|
-
};
|
|
953
|
-
planModeFlagsByConversationKey.set(conversationKey, created);
|
|
954
|
-
return created;
|
|
955
|
-
}
|
|
956
|
-
function getMaxParallelExploreAgents() {
|
|
957
|
-
const raw = process.env.KODE_PLAN_V2_EXPLORE_AGENT_COUNT ?? process.env.CLAUDE_CODE_PLAN_V2_EXPLORE_AGENT_COUNT;
|
|
958
|
-
if (raw) {
|
|
959
|
-
const parsed = Number.parseInt(raw, 10);
|
|
960
|
-
if (Number.isFinite(parsed) && parsed > 0 && parsed <= 10) return parsed;
|
|
961
|
-
}
|
|
962
|
-
return 3;
|
|
963
|
-
}
|
|
964
|
-
function getMaxParallelPlanAgents() {
|
|
965
|
-
const raw = process.env.KODE_PLAN_V2_AGENT_COUNT ?? process.env.CLAUDE_CODE_PLAN_V2_AGENT_COUNT;
|
|
966
|
-
if (raw) {
|
|
967
|
-
const parsed = Number.parseInt(raw, 10);
|
|
968
|
-
if (Number.isFinite(parsed) && parsed > 0 && parsed <= 10) return parsed;
|
|
969
|
-
}
|
|
970
|
-
return 1;
|
|
971
|
-
}
|
|
972
|
-
function buildPlanModeMainReminder(args) {
|
|
973
|
-
const {
|
|
974
|
-
planExists,
|
|
975
|
-
planFilePath,
|
|
976
|
-
maxParallelExploreAgents,
|
|
977
|
-
maxParallelPlanAgents
|
|
978
|
-
} = args;
|
|
979
|
-
const writeToolName = "Write";
|
|
980
|
-
const editToolName = "Edit";
|
|
981
|
-
const askUserToolName = "AskUserQuestion";
|
|
982
|
-
const exploreAgentType = "Explore";
|
|
983
|
-
const planAgentType = "Plan";
|
|
984
|
-
const exitPlanModeToolName = "ExitPlanMode";
|
|
985
|
-
return `Plan mode is active. The user indicated that they do not want you to execute yet -- you MUST NOT make any edits (with the exception of the plan file mentioned below), run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supercedes any other instructions you have received.
|
|
986
|
-
|
|
987
|
-
## Plan File Info:
|
|
988
|
-
${planExists ? `A plan file already exists at ${planFilePath}. You can read it and make incremental edits using the ${editToolName} tool.` : `No plan file exists yet. You should create your plan at ${planFilePath} using the ${writeToolName} tool.`}
|
|
989
|
-
You should build your plan incrementally by writing to or editing this file. NOTE that this is the only file you are allowed to edit - other than this you are only allowed to take READ-ONLY actions.
|
|
990
|
-
|
|
991
|
-
## Plan Workflow
|
|
992
|
-
|
|
993
|
-
### Phase 1: Initial Understanding
|
|
994
|
-
Goal: Gain a comprehensive understanding of the user's request by reading through code and asking them questions. Critical: In this phase you should only use the ${exploreAgentType} subagent type.
|
|
995
|
-
|
|
996
|
-
1. Focus on understanding the user's request and the code associated with their request
|
|
997
|
-
|
|
998
|
-
2. **Launch up to ${maxParallelExploreAgents} ${exploreAgentType} agents IN PARALLEL** (single message, multiple tool calls) to efficiently explore the codebase.
|
|
999
|
-
- Use 1 agent when the task is isolated to known files, the user provided specific file paths, or you're making a small targeted change.
|
|
1000
|
-
- Use multiple agents when: the scope is uncertain, multiple areas of the codebase are involved, or you need to understand existing patterns before planning.
|
|
1001
|
-
- Quality over quantity - ${maxParallelExploreAgents} agents maximum, but you should try to use the minimum number of agents necessary (usually just 1)
|
|
1002
|
-
- If using multiple agents: Provide each agent with a specific search focus or area to explore. Example: One agent searches for existing implementations, another explores related components, a third investigates testing patterns
|
|
1003
|
-
|
|
1004
|
-
3. After exploring the code, use the ${askUserToolName} tool to clarify ambiguities in the user request up front.
|
|
1005
|
-
|
|
1006
|
-
### Phase 2: Design
|
|
1007
|
-
Goal: Design an implementation approach.
|
|
1008
|
-
|
|
1009
|
-
Launch ${planAgentType} agent(s) to design the implementation based on the user's intent and your exploration results from Phase 1.
|
|
1010
|
-
|
|
1011
|
-
You can launch up to ${maxParallelPlanAgents} agent(s) in parallel.
|
|
1012
|
-
|
|
1013
|
-
**Guidelines:**
|
|
1014
|
-
- **Default**: Launch at least 1 Plan agent for most tasks - it helps validate your understanding and consider alternatives
|
|
1015
|
-
- **Skip agents**: Only for truly trivial tasks (typo fixes, single-line changes, simple renames)
|
|
1016
|
-
${maxParallelPlanAgents > 1 ? `- **Multiple agents**: Use up to ${maxParallelPlanAgents} agents for complex tasks that benefit from different perspectives
|
|
1017
|
-
|
|
1018
|
-
Examples of when to use multiple agents:
|
|
1019
|
-
- The task touches multiple parts of the codebase
|
|
1020
|
-
- It's a large refactor or architectural change
|
|
1021
|
-
- There are many edge cases to consider
|
|
1022
|
-
- You'd benefit from exploring different approaches
|
|
1023
|
-
|
|
1024
|
-
Example perspectives by task type:
|
|
1025
|
-
- New feature: simplicity vs performance vs maintainability
|
|
1026
|
-
- Bug fix: root cause vs workaround vs prevention
|
|
1027
|
-
- Refactoring: minimal change vs clean architecture
|
|
1028
|
-
` : ""}
|
|
1029
|
-
In the agent prompt:
|
|
1030
|
-
- Provide comprehensive background context from Phase 1 exploration including filenames and code path traces
|
|
1031
|
-
- Describe requirements and constraints
|
|
1032
|
-
- Request a detailed implementation plan
|
|
1033
|
-
|
|
1034
|
-
### Phase 3: Review
|
|
1035
|
-
Goal: Review the plan(s) from Phase 2 and ensure alignment with the user's intentions.
|
|
1036
|
-
1. Read the critical files identified by agents to deepen your understanding
|
|
1037
|
-
2. Ensure that the plans align with the user's original request
|
|
1038
|
-
3. Use ${askUserToolName} to clarify any remaining questions with the user
|
|
1039
|
-
|
|
1040
|
-
### Phase 4: Final Plan
|
|
1041
|
-
Goal: Write your final plan to the plan file (the only file you can edit).
|
|
1042
|
-
- Include only your recommended approach, not all alternatives
|
|
1043
|
-
- Ensure that the plan file is concise enough to scan quickly, but detailed enough to execute effectively
|
|
1044
|
-
- Include the paths of critical files to be modified
|
|
1045
|
-
|
|
1046
|
-
### Phase 5: Call ${exitPlanModeToolName}
|
|
1047
|
-
At the very end of your turn, once you have asked the user questions and are happy with your final plan file - you should always call ${exitPlanModeToolName} to indicate to the user that you are done planning.
|
|
1048
|
-
This is critical - your turn should only end with either asking the user a question or calling ${exitPlanModeToolName}. Do not stop unless it's for these 2 reasons.
|
|
1049
|
-
|
|
1050
|
-
NOTE: At any point in time through this workflow you should feel free to ask the user questions or clarifications. Don't make large assumptions about user intent. The goal is to present a well researched plan to the user, and tie any loose ends before implementation begins.`;
|
|
1051
|
-
}
|
|
1052
|
-
function buildPlanModeSubAgentReminder(args) {
|
|
1053
|
-
const { planExists, planFilePath } = args;
|
|
1054
|
-
const writeToolName = "Write";
|
|
1055
|
-
const editToolName = "Edit";
|
|
1056
|
-
const askUserToolName = "AskUserQuestion";
|
|
1057
|
-
return `Plan mode is active. The user indicated that they do not want you to execute yet -- you MUST NOT make any edits, run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supercedes any other instructions you have received (for example, to make edits). Instead, you should:
|
|
1058
|
-
|
|
1059
|
-
## Plan File Info:
|
|
1060
|
-
${planExists ? `A plan file already exists at ${planFilePath}. You can read it and make incremental edits using the ${editToolName} tool if you need to.` : `No plan file exists yet. You should create your plan at ${planFilePath} using the ${writeToolName} tool if you need to.`}
|
|
1061
|
-
You should build your plan incrementally by writing to or editing this file. NOTE that this is the only file you are allowed to edit - other than this you are only allowed to take READ-ONLY actions.
|
|
1062
|
-
Answer the user's query comprehensively, using the ${askUserToolName} tool if you need to ask the user clarifying questions. If you do use the ${askUserToolName}, make sure to ask all clarifying questions you need to fully understand the user's intent before proceeding.`;
|
|
1063
|
-
}
|
|
1064
|
-
function buildPlanModeReentryReminder(planFilePath) {
|
|
1065
|
-
const exitPlanModeToolName = "ExitPlanMode";
|
|
1066
|
-
return `## Re-entering Plan Mode
|
|
1067
|
-
|
|
1068
|
-
You are returning to plan mode after having previously exited it. A plan file exists at ${planFilePath} from your previous planning session.
|
|
1069
|
-
|
|
1070
|
-
**Before proceeding with any new planning, you should:**
|
|
1071
|
-
1. Read the existing plan file to understand what was previously planned
|
|
1072
|
-
2. Evaluate the user's current request against that plan
|
|
1073
|
-
3. Decide how to proceed:
|
|
1074
|
-
- **Different task**: If the user's request is for a different task\u2014even if it's similar or related\u2014start fresh by overwriting the existing plan
|
|
1075
|
-
- **Same task, continuing**: If this is explicitly a continuation or refinement of the exact same task, modify the existing plan while cleaning up outdated or irrelevant sections
|
|
1076
|
-
4. Continue on with the plan process and most importantly you should always edit the plan file one way or the other before calling ${exitPlanModeToolName}
|
|
1077
|
-
|
|
1078
|
-
Treat this as a fresh planning session. Do not assume the existing plan is relevant without evaluating it first.`;
|
|
1079
|
-
}
|
|
1080
|
-
function buildPlanModeExitReminder(planFilePath) {
|
|
1081
|
-
return `## Exited Plan Mode
|
|
1082
|
-
|
|
1083
|
-
You have exited plan mode. You can now make edits, run tools, and take actions. The plan file is located at ${planFilePath} if you need to reference it.`;
|
|
1084
|
-
}
|
|
1085
|
-
function wrapSystemReminder(text) {
|
|
1086
|
-
return `<system-reminder>
|
|
1087
|
-
${text}
|
|
1088
|
-
</system-reminder>`;
|
|
1089
|
-
}
|
|
1090
|
-
function getPlanModeSystemPromptAdditions(messages, context) {
|
|
1091
|
-
const conversationKey = getConversationKey(context);
|
|
1092
|
-
const agentKey = getAgentKey(context);
|
|
1093
|
-
const flags = getOrCreatePlanModeFlags(conversationKey);
|
|
1094
|
-
const additions = [];
|
|
1095
|
-
const assistantTurns = messages.filter((m) => m?.type === "assistant").length;
|
|
1096
|
-
if (isPlanModeEnabled(context)) {
|
|
1097
|
-
const previous = planModeAttachmentStateByAgentKey.get(agentKey) ?? {
|
|
1098
|
-
hasInjected: false,
|
|
1099
|
-
lastInjectedAssistantTurn: -Infinity
|
|
1100
|
-
};
|
|
1101
|
-
if (previous.hasInjected && assistantTurns - previous.lastInjectedAssistantTurn < TURNS_BETWEEN_ATTACHMENTS) {
|
|
1102
|
-
return [];
|
|
1103
|
-
}
|
|
1104
|
-
const planFilePath = getPlanFilePath(context.agentId, conversationKey);
|
|
1105
|
-
const planExists = existsSync(planFilePath);
|
|
1106
|
-
if (flags.hasExitedPlanMode && planExists) {
|
|
1107
|
-
additions.push(
|
|
1108
|
-
wrapSystemReminder(buildPlanModeReentryReminder(planFilePath))
|
|
1109
|
-
);
|
|
1110
|
-
flags.hasExitedPlanMode = false;
|
|
1111
|
-
}
|
|
1112
|
-
const isSubAgent = !!context.agentId;
|
|
1113
|
-
additions.push(
|
|
1114
|
-
wrapSystemReminder(
|
|
1115
|
-
isSubAgent ? buildPlanModeSubAgentReminder({ planExists, planFilePath }) : buildPlanModeMainReminder({
|
|
1116
|
-
planExists,
|
|
1117
|
-
planFilePath,
|
|
1118
|
-
maxParallelExploreAgents: getMaxParallelExploreAgents(),
|
|
1119
|
-
maxParallelPlanAgents: getMaxParallelPlanAgents()
|
|
1120
|
-
})
|
|
1121
|
-
)
|
|
1122
|
-
);
|
|
1123
|
-
planModeFlagsByConversationKey.set(conversationKey, flags);
|
|
1124
|
-
planModeAttachmentStateByAgentKey.set(agentKey, {
|
|
1125
|
-
hasInjected: true,
|
|
1126
|
-
lastInjectedAssistantTurn: assistantTurns
|
|
1127
|
-
});
|
|
1128
|
-
return additions;
|
|
1129
|
-
}
|
|
1130
|
-
if (flags.needsPlanModeExitAttachment) {
|
|
1131
|
-
const planFilePath = getPlanFilePath(context.agentId, conversationKey);
|
|
1132
|
-
additions.push(wrapSystemReminder(buildPlanModeExitReminder(planFilePath)));
|
|
1133
|
-
flags.needsPlanModeExitAttachment = false;
|
|
1134
|
-
planModeFlagsByConversationKey.set(conversationKey, flags);
|
|
1135
|
-
}
|
|
1136
|
-
return additions;
|
|
1137
|
-
}
|
|
1138
|
-
function isPlanModeEnabled(context) {
|
|
1139
|
-
const key = getConversationKey(context);
|
|
1140
|
-
return planModeEnabledByConversationKey.get(key) ?? false;
|
|
1141
|
-
}
|
|
1142
|
-
function enterPlanMode(context) {
|
|
1143
|
-
const key = getConversationKey(context);
|
|
1144
|
-
planModeEnabledByConversationKey.set(key, true);
|
|
1145
|
-
return { planFilePath: getPlanFilePath(context?.agentId, key) };
|
|
1146
|
-
}
|
|
1147
|
-
function enterPlanModeForConversationKey(conversationKey) {
|
|
1148
|
-
planModeEnabledByConversationKey.set(conversationKey, true);
|
|
1149
|
-
}
|
|
1150
|
-
function exitPlanModeForConversationKey(conversationKey) {
|
|
1151
|
-
planModeEnabledByConversationKey.set(conversationKey, false);
|
|
1152
|
-
const flags = getOrCreatePlanModeFlags(conversationKey);
|
|
1153
|
-
flags.hasExitedPlanMode = true;
|
|
1154
|
-
flags.needsPlanModeExitAttachment = true;
|
|
1155
|
-
planModeFlagsByConversationKey.set(conversationKey, flags);
|
|
1156
|
-
}
|
|
1157
|
-
function getPlanSlugForConversationKey(conversationKey) {
|
|
1158
|
-
return planSlugCache.get(conversationKey) ?? null;
|
|
1159
|
-
}
|
|
1160
|
-
function hydratePlanSlugFromMessages(messages, context) {
|
|
1161
|
-
const conversationKey = getConversationKey(context);
|
|
1162
|
-
if (planSlugCache.has(conversationKey)) return true;
|
|
1163
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1164
|
-
const msg = messages[i];
|
|
1165
|
-
const directSlug = typeof msg?.slug === "string" ? msg.slug.trim() : "";
|
|
1166
|
-
if (directSlug) {
|
|
1167
|
-
planSlugCache.set(conversationKey, directSlug);
|
|
1168
|
-
return true;
|
|
1169
|
-
}
|
|
1170
|
-
const data = msg?.toolUseResult?.data;
|
|
1171
|
-
if (!data || typeof data !== "object") continue;
|
|
1172
|
-
const planFilePath = typeof data.planFilePath === "string" ? data.planFilePath : typeof data.filePath === "string" ? data.filePath : null;
|
|
1173
|
-
if (!planFilePath) continue;
|
|
1174
|
-
const slug = extractSlugFromPlanFilePath(planFilePath);
|
|
1175
|
-
if (!slug) continue;
|
|
1176
|
-
planSlugCache.set(conversationKey, slug);
|
|
1177
|
-
return true;
|
|
1178
|
-
}
|
|
1179
|
-
return false;
|
|
1180
|
-
}
|
|
1181
|
-
function getPlanDirectory() {
|
|
1182
|
-
const dir = join2(getKodeBaseDir(), "plans");
|
|
1183
|
-
if (!existsSync(dir)) {
|
|
1184
|
-
mkdirSync(dir, { recursive: true });
|
|
1185
|
-
}
|
|
1186
|
-
return dir;
|
|
1187
|
-
}
|
|
1188
|
-
function getPlanFilePath(agentId, conversationKey) {
|
|
1189
|
-
const dir = getPlanDirectory();
|
|
1190
|
-
const key = conversationKey ?? DEFAULT_CONVERSATION_KEY;
|
|
1191
|
-
const slug = getOrCreatePlanSlug(key);
|
|
1192
|
-
if (!agentId) return join2(dir, `${slug}.md`);
|
|
1193
|
-
return join2(dir, `${slug}-agent-${agentId}.md`);
|
|
1194
|
-
}
|
|
1195
|
-
function resolveExistingPath(path) {
|
|
1196
|
-
const resolved = resolve(path);
|
|
1197
|
-
try {
|
|
1198
|
-
return realpathSync(resolved);
|
|
1199
|
-
} catch {
|
|
1200
|
-
return resolved;
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
function isMainPlanFilePathForActiveConversation(path) {
|
|
1204
|
-
const key = activePlanConversationKey ?? DEFAULT_CONVERSATION_KEY;
|
|
1205
|
-
const expected = resolveExistingPath(getPlanFilePath(void 0, key));
|
|
1206
|
-
const target = resolveExistingPath(path);
|
|
1207
|
-
return target === expected;
|
|
1208
|
-
}
|
|
1209
|
-
function readPlanFile(agentId, conversationKey) {
|
|
1210
|
-
const planFilePath = getPlanFilePath(agentId, conversationKey);
|
|
1211
|
-
if (!existsSync(planFilePath)) {
|
|
1212
|
-
return { content: "", exists: false, planFilePath };
|
|
1213
|
-
}
|
|
1214
|
-
return {
|
|
1215
|
-
content: readFileSync(planFilePath, "utf8"),
|
|
1216
|
-
exists: true,
|
|
1217
|
-
planFilePath
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
// src/utils/log/index.ts
|
|
1222
|
-
var IN_MEMORY_ERROR_LOG = [];
|
|
1223
|
-
var MAX_IN_MEMORY_ERRORS = 100;
|
|
1224
|
-
var PERMISSION_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EPERM", "EROFS"]);
|
|
1225
|
-
function isPermissionError(error) {
|
|
1226
|
-
return typeof error === "object" && error !== null && "code" in error && PERMISSION_ERROR_CODES.has(error.code ?? "");
|
|
1227
|
-
}
|
|
1228
|
-
function safeMkdir(dir) {
|
|
1229
|
-
if (existsSync2(dir)) return true;
|
|
1230
|
-
try {
|
|
1231
|
-
mkdirSync2(dir, { recursive: true });
|
|
1232
|
-
return true;
|
|
1233
|
-
} catch (error) {
|
|
1234
|
-
if (isPermissionError(error)) {
|
|
1235
|
-
return false;
|
|
1236
|
-
}
|
|
1237
|
-
throw error;
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
function safeWriteFile(path, data, encoding = "utf8") {
|
|
1241
|
-
try {
|
|
1242
|
-
writeFileSync(path, data, encoding);
|
|
1243
|
-
return true;
|
|
1244
|
-
} catch (error) {
|
|
1245
|
-
if (isPermissionError(error)) {
|
|
1246
|
-
return false;
|
|
1247
|
-
}
|
|
1248
|
-
throw error;
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
var SESSION_ID = randomUUID();
|
|
1252
|
-
var paths = envPaths(PRODUCT_COMMAND);
|
|
1253
|
-
function getProjectDir(cwd2) {
|
|
1254
|
-
return cwd2.replace(/[^a-zA-Z0-9]/g, "-");
|
|
1255
|
-
}
|
|
1256
|
-
function getLegacyCacheRoot() {
|
|
1257
|
-
return process.env.KODE_LEGACY_CACHE_ROOT ?? paths.cache;
|
|
1258
|
-
}
|
|
1259
|
-
function getNewLogRoot() {
|
|
1260
|
-
return process.env.KODE_LOG_ROOT ?? getKodeBaseDir();
|
|
1261
|
-
}
|
|
1262
|
-
var CACHE_PATHS = {
|
|
1263
|
-
errors: () => join3(getNewLogRoot(), getProjectDir(process.cwd()), "errors"),
|
|
1264
|
-
messages: () => join3(getNewLogRoot(), getProjectDir(process.cwd()), "messages"),
|
|
1265
|
-
mcpLogs: (serverName) => join3(
|
|
1266
|
-
getLegacyCacheRoot(),
|
|
1267
|
-
getProjectDir(process.cwd()),
|
|
1268
|
-
`mcp-logs-${serverName}`
|
|
1269
|
-
)
|
|
1270
|
-
};
|
|
1271
|
-
var LEGACY_CACHE_PATHS = {
|
|
1272
|
-
errors: () => join3(getLegacyCacheRoot(), getProjectDir(process.cwd()), "errors"),
|
|
1273
|
-
messages: () => join3(getLegacyCacheRoot(), getProjectDir(process.cwd()), "messages"),
|
|
1274
|
-
mcpLogs: (serverName) => join3(
|
|
1275
|
-
getLegacyCacheRoot(),
|
|
1276
|
-
getProjectDir(process.cwd()),
|
|
1277
|
-
`mcp-logs-${serverName}`
|
|
1278
|
-
)
|
|
1279
|
-
};
|
|
1280
|
-
function dateToFilename(date) {
|
|
1281
|
-
return date.toISOString().replace(/[:.]/g, "-");
|
|
1282
|
-
}
|
|
1283
|
-
var DATE = dateToFilename(/* @__PURE__ */ new Date());
|
|
1284
|
-
function getErrorsPath() {
|
|
1285
|
-
return join3(CACHE_PATHS.errors(), DATE + ".txt");
|
|
1286
|
-
}
|
|
1287
|
-
function getMessagesPath(messageLogName, forkNumber, sidechainNumber) {
|
|
1288
|
-
return join3(
|
|
1289
|
-
CACHE_PATHS.messages(),
|
|
1290
|
-
`${messageLogName}${forkNumber > 0 ? `-${forkNumber}` : ""}${sidechainNumber > 0 ? `-sidechain-${sidechainNumber}` : ""}.json`
|
|
1291
|
-
);
|
|
1292
|
-
}
|
|
1293
|
-
var MIGRATION_MESSAGE_LOG_LIMIT = 50;
|
|
1294
|
-
var didMigrateMessageLogs = false;
|
|
1295
|
-
function migrateLegacyMessageLogsIfNeeded() {
|
|
1296
|
-
if (didMigrateMessageLogs) return;
|
|
1297
|
-
didMigrateMessageLogs = true;
|
|
1298
|
-
const legacyDir = LEGACY_CACHE_PATHS.messages();
|
|
1299
|
-
const newDir = CACHE_PATHS.messages();
|
|
1300
|
-
if (!existsSync2(legacyDir)) return;
|
|
1301
|
-
const newHasAny = existsSync2(newDir) && readdirSync(newDir).some((file) => file.endsWith(".json"));
|
|
1302
|
-
if (newHasAny) return;
|
|
1303
|
-
try {
|
|
1304
|
-
mkdirSync2(newDir, { recursive: true });
|
|
1305
|
-
} catch {
|
|
1306
|
-
return;
|
|
1307
|
-
}
|
|
1308
|
-
let legacyFiles = [];
|
|
1309
|
-
try {
|
|
1310
|
-
legacyFiles = readdirSync(legacyDir).filter((file) => file.endsWith(".json"));
|
|
1311
|
-
} catch {
|
|
1312
|
-
return;
|
|
1313
|
-
}
|
|
1314
|
-
const sorted = legacyFiles.map((file) => {
|
|
1315
|
-
try {
|
|
1316
|
-
const stats = statSync(join3(legacyDir, file));
|
|
1317
|
-
return { file, mtimeMs: stats.mtimeMs };
|
|
1318
|
-
} catch {
|
|
1319
|
-
return { file, mtimeMs: 0 };
|
|
1320
|
-
}
|
|
1321
|
-
}).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, MIGRATION_MESSAGE_LOG_LIMIT);
|
|
1322
|
-
for (const { file } of sorted) {
|
|
1323
|
-
const src = join3(legacyDir, file);
|
|
1324
|
-
const dest = join3(newDir, file);
|
|
1325
|
-
if (existsSync2(dest)) continue;
|
|
1326
|
-
try {
|
|
1327
|
-
copyFileSync(src, dest);
|
|
1328
|
-
} catch {
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
function logError(error) {
|
|
1333
|
-
try {
|
|
1334
|
-
if (process.env.NODE_ENV === "test") {
|
|
1335
|
-
console.error(error);
|
|
1336
|
-
}
|
|
1337
|
-
const errorStr = error instanceof Error ? error.stack || error.message : String(error);
|
|
1338
|
-
const errorInfo = {
|
|
1339
|
-
error: errorStr,
|
|
1340
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1341
|
-
};
|
|
1342
|
-
if (IN_MEMORY_ERROR_LOG.length >= MAX_IN_MEMORY_ERRORS) {
|
|
1343
|
-
IN_MEMORY_ERROR_LOG.shift();
|
|
1344
|
-
}
|
|
1345
|
-
IN_MEMORY_ERROR_LOG.push(errorInfo);
|
|
1346
|
-
appendToLog(getErrorsPath(), {
|
|
1347
|
-
error: errorStr
|
|
1348
|
-
});
|
|
1349
|
-
} catch {
|
|
1350
|
-
}
|
|
1351
|
-
captureException(error);
|
|
1352
|
-
}
|
|
1353
|
-
function readLog(path) {
|
|
1354
|
-
if (!existsSync2(path)) {
|
|
1355
|
-
return [];
|
|
1356
|
-
}
|
|
1357
|
-
try {
|
|
1358
|
-
return JSON.parse(readFileSync2(path, "utf8"));
|
|
1359
|
-
} catch {
|
|
1360
|
-
return [];
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
function appendToLog(path, message) {
|
|
1364
|
-
if (process.env.USER_TYPE === "external") {
|
|
1365
|
-
return;
|
|
1366
|
-
}
|
|
1367
|
-
const dir = dirname(path);
|
|
1368
|
-
if (!safeMkdir(dir)) {
|
|
1369
|
-
return;
|
|
1370
|
-
}
|
|
1371
|
-
if (!existsSync2(path) && !safeWriteFile(path, "[]")) {
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
|
-
const messages = readLog(path);
|
|
1375
|
-
const messageWithTimestamp = {
|
|
1376
|
-
...message,
|
|
1377
|
-
cwd: process.cwd(),
|
|
1378
|
-
userType: process.env.USER_TYPE,
|
|
1379
|
-
sessionId: SESSION_ID,
|
|
1380
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1381
|
-
version: MACRO.VERSION
|
|
1382
|
-
};
|
|
1383
|
-
messages.push(messageWithTimestamp);
|
|
1384
|
-
safeWriteFile(path, JSON.stringify(messages, null, 2));
|
|
1385
|
-
}
|
|
1386
|
-
function overwriteLog(path, messages, options) {
|
|
1387
|
-
if (process.env.USER_TYPE === "external") {
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
if (!messages.length) {
|
|
1391
|
-
return;
|
|
1392
|
-
}
|
|
1393
|
-
const dir = dirname(path);
|
|
1394
|
-
if (!safeMkdir(dir)) {
|
|
1395
|
-
return;
|
|
1396
|
-
}
|
|
1397
|
-
const slug = options?.conversationKey ? getPlanSlugForConversationKey(options.conversationKey) : null;
|
|
1398
|
-
const messagesWithMetadata = messages.map((message) => ({
|
|
1399
|
-
...message,
|
|
1400
|
-
...slug ? { slug } : {},
|
|
1401
|
-
cwd: process.cwd(),
|
|
1402
|
-
userType: process.env.USER_TYPE,
|
|
1403
|
-
sessionId: SESSION_ID,
|
|
1404
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1405
|
-
version: MACRO.VERSION
|
|
1406
|
-
}));
|
|
1407
|
-
safeWriteFile(path, JSON.stringify(messagesWithMetadata, null, 2));
|
|
1408
|
-
}
|
|
1409
|
-
async function loadLogList(path = CACHE_PATHS.messages()) {
|
|
1410
|
-
if (path === CACHE_PATHS.messages()) {
|
|
1411
|
-
migrateLegacyMessageLogsIfNeeded();
|
|
1412
|
-
}
|
|
1413
|
-
const searchPaths = path === CACHE_PATHS.messages() ? [CACHE_PATHS.messages(), LEGACY_CACHE_PATHS.messages()] : [path];
|
|
1414
|
-
const existingPaths = searchPaths.filter((p) => existsSync2(p));
|
|
1415
|
-
if (existingPaths.length === 0) {
|
|
1416
|
-
logError(`No logs found at ${path}`);
|
|
1417
|
-
return [];
|
|
1418
|
-
}
|
|
1419
|
-
const filesWithDir = (await Promise.all(
|
|
1420
|
-
existingPaths.map(async (dirPath) => {
|
|
1421
|
-
const dirFiles = await fsPromises.readdir(dirPath);
|
|
1422
|
-
return dirFiles.map((file) => ({ file, dirPath }));
|
|
1423
|
-
})
|
|
1424
|
-
)).flat();
|
|
1425
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1426
|
-
const uniqueFiles = filesWithDir.filter(({ file }) => {
|
|
1427
|
-
if (seen.has(file)) return false;
|
|
1428
|
-
seen.add(file);
|
|
1429
|
-
return true;
|
|
1430
|
-
});
|
|
1431
|
-
const logData = await Promise.all(
|
|
1432
|
-
uniqueFiles.map(async ({ file, dirPath }, i) => {
|
|
1433
|
-
const fullPath = join3(dirPath, file);
|
|
1434
|
-
const content = await fsPromises.readFile(fullPath, "utf8");
|
|
1435
|
-
const messages = JSON.parse(content);
|
|
1436
|
-
const firstMessage = messages[0];
|
|
1437
|
-
const lastMessage = messages[messages.length - 1];
|
|
1438
|
-
const firstPrompt = firstMessage?.type === "user" && typeof firstMessage?.message?.content === "string" ? firstMessage?.message?.content : "No prompt";
|
|
1439
|
-
const { date, forkNumber, sidechainNumber } = parseLogFilename(file);
|
|
1440
|
-
return {
|
|
1441
|
-
date,
|
|
1442
|
-
forkNumber,
|
|
1443
|
-
fullPath,
|
|
1444
|
-
messages,
|
|
1445
|
-
value: i,
|
|
1446
|
-
created: parseISOString(firstMessage?.timestamp || date),
|
|
1447
|
-
modified: lastMessage?.timestamp ? parseISOString(lastMessage.timestamp) : parseISOString(date),
|
|
1448
|
-
firstPrompt: firstPrompt.split("\n")[0]?.slice(0, 50) + (firstPrompt.length > 50 ? "\u2026" : "") || "No prompt",
|
|
1449
|
-
messageCount: messages.length,
|
|
1450
|
-
sidechainNumber
|
|
1451
|
-
};
|
|
1452
|
-
})
|
|
1453
|
-
);
|
|
1454
|
-
return sortLogs(logData.filter((_) => _.messages.length)).map((_, i) => ({
|
|
1455
|
-
..._,
|
|
1456
|
-
value: i
|
|
1457
|
-
}));
|
|
1458
|
-
}
|
|
1459
|
-
function parseLogFilename(filename) {
|
|
1460
|
-
const base = filename.split(".")[0];
|
|
1461
|
-
const segments = base.split("-");
|
|
1462
|
-
const hasSidechain = base.includes("-sidechain-");
|
|
1463
|
-
let date = base;
|
|
1464
|
-
let forkNumber = void 0;
|
|
1465
|
-
let sidechainNumber = void 0;
|
|
1466
|
-
if (hasSidechain) {
|
|
1467
|
-
const sidechainIndex = segments.indexOf("sidechain");
|
|
1468
|
-
sidechainNumber = Number(segments[sidechainIndex + 1]);
|
|
1469
|
-
if (sidechainIndex > 6) {
|
|
1470
|
-
forkNumber = Number(segments[sidechainIndex - 1]);
|
|
1471
|
-
date = segments.slice(0, 6).join("-");
|
|
1472
|
-
} else {
|
|
1473
|
-
date = segments.slice(0, 6).join("-");
|
|
1474
|
-
}
|
|
1475
|
-
} else if (segments.length > 6) {
|
|
1476
|
-
const lastSegment = Number(segments[segments.length - 1]);
|
|
1477
|
-
forkNumber = lastSegment >= 0 ? lastSegment : void 0;
|
|
1478
|
-
date = segments.slice(0, 6).join("-");
|
|
1479
|
-
} else {
|
|
1480
|
-
date = base;
|
|
1481
|
-
}
|
|
1482
|
-
return { date, forkNumber, sidechainNumber };
|
|
1483
|
-
}
|
|
1484
|
-
function getNextAvailableLogForkNumber(date, forkNumber, sidechainNumber) {
|
|
1485
|
-
while (existsSync2(getMessagesPath(date, forkNumber, sidechainNumber))) {
|
|
1486
|
-
forkNumber++;
|
|
1487
|
-
}
|
|
1488
|
-
return forkNumber;
|
|
1489
|
-
}
|
|
1490
|
-
function getNextAvailableLogSidechainNumber(date, forkNumber) {
|
|
1491
|
-
let sidechainNumber = 1;
|
|
1492
|
-
while (existsSync2(getMessagesPath(date, forkNumber, sidechainNumber))) {
|
|
1493
|
-
sidechainNumber++;
|
|
1494
|
-
}
|
|
1495
|
-
return sidechainNumber;
|
|
1496
|
-
}
|
|
1497
|
-
function sortLogs(logs) {
|
|
1498
|
-
return logs.sort((a, b) => {
|
|
1499
|
-
const modifiedDiff = b.modified.getTime() - a.modified.getTime();
|
|
1500
|
-
if (modifiedDiff !== 0) {
|
|
1501
|
-
return modifiedDiff;
|
|
1502
|
-
}
|
|
1503
|
-
const createdDiff = b.created.getTime() - a.created.getTime();
|
|
1504
|
-
if (createdDiff !== 0) {
|
|
1505
|
-
return createdDiff;
|
|
1506
|
-
}
|
|
1507
|
-
return (b.forkNumber ?? 0) - (a.forkNumber ?? 0);
|
|
1508
|
-
});
|
|
1509
|
-
}
|
|
1510
|
-
function formatDate(date) {
|
|
1511
|
-
const now = /* @__PURE__ */ new Date();
|
|
1512
|
-
const yesterday = new Date(now);
|
|
1513
|
-
yesterday.setDate(yesterday.getDate() - 1);
|
|
1514
|
-
const isToday = date.toDateString() === now.toDateString();
|
|
1515
|
-
const isYesterday = date.toDateString() === yesterday.toDateString();
|
|
1516
|
-
const timeStr = date.toLocaleTimeString("en-US", {
|
|
1517
|
-
hour: "numeric",
|
|
1518
|
-
minute: "2-digit",
|
|
1519
|
-
hour12: true
|
|
1520
|
-
}).toLowerCase();
|
|
1521
|
-
if (isToday) {
|
|
1522
|
-
return `Today at ${timeStr}`;
|
|
1523
|
-
} else if (isYesterday) {
|
|
1524
|
-
return `Yesterday at ${timeStr}`;
|
|
1525
|
-
} else {
|
|
1526
|
-
return date.toLocaleDateString("en-US", {
|
|
1527
|
-
month: "short",
|
|
1528
|
-
day: "numeric"
|
|
1529
|
-
}) + ` at ${timeStr}`;
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
function parseISOString(s) {
|
|
1533
|
-
const b = s.split(/\D+/);
|
|
1534
|
-
return new Date(
|
|
1535
|
-
Date.UTC(
|
|
1536
|
-
parseInt(b[0], 10),
|
|
1537
|
-
parseInt(b[1], 10) - 1,
|
|
1538
|
-
parseInt(b[2], 10),
|
|
1539
|
-
parseInt(b[3], 10),
|
|
1540
|
-
parseInt(b[4], 10),
|
|
1541
|
-
parseInt(b[5], 10),
|
|
1542
|
-
parseInt(b[6], 10)
|
|
1543
|
-
)
|
|
1544
|
-
);
|
|
1545
|
-
}
|
|
1546
|
-
function logMCPError(serverName, error) {
|
|
1547
|
-
try {
|
|
1548
|
-
const logDir = CACHE_PATHS.mcpLogs(serverName);
|
|
1549
|
-
const errorStr = error instanceof Error ? error.stack || error.message : String(error);
|
|
1550
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1551
|
-
const logFile = join3(logDir, DATE + ".txt");
|
|
1552
|
-
if (!existsSync2(logDir)) {
|
|
1553
|
-
mkdirSync2(logDir, { recursive: true });
|
|
1554
|
-
}
|
|
1555
|
-
if (!existsSync2(logFile)) {
|
|
1556
|
-
writeFileSync(logFile, "[]", "utf8");
|
|
1557
|
-
}
|
|
1558
|
-
const errorInfo = {
|
|
1559
|
-
error: errorStr,
|
|
1560
|
-
timestamp,
|
|
1561
|
-
sessionId: SESSION_ID,
|
|
1562
|
-
cwd: process.cwd()
|
|
1563
|
-
};
|
|
1564
|
-
const messages = readLog(logFile);
|
|
1565
|
-
messages.push(errorInfo);
|
|
1566
|
-
writeFileSync(logFile, JSON.stringify(messages, null, 2), "utf8");
|
|
1567
|
-
} catch {
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
// src/utils/log/taskOutputStore.ts
|
|
1572
|
-
import {
|
|
1573
|
-
appendFileSync,
|
|
1574
|
-
existsSync as existsSync3,
|
|
1575
|
-
mkdirSync as mkdirSync3,
|
|
1576
|
-
readFileSync as readFileSync3,
|
|
1577
|
-
statSync as statSync2,
|
|
1578
|
-
writeFileSync as writeFileSync2
|
|
1579
|
-
} from "fs";
|
|
1580
|
-
import { dirname as dirname2, join as join4 } from "path";
|
|
1581
|
-
function getProjectDir2(cwd2) {
|
|
1582
|
-
return cwd2.replace(/[^a-zA-Z0-9]/g, "-");
|
|
1583
|
-
}
|
|
1584
|
-
var PROJECT_ROOT = process.cwd();
|
|
1585
|
-
function getTaskOutputsDir() {
|
|
1586
|
-
return join4(getKodeBaseDir(), getProjectDir2(PROJECT_ROOT), "tasks");
|
|
1587
|
-
}
|
|
1588
|
-
function getTaskOutputFilePath(taskId) {
|
|
1589
|
-
return join4(getTaskOutputsDir(), `${taskId}.output`);
|
|
1590
|
-
}
|
|
1591
|
-
function ensureTaskOutputsDirExists() {
|
|
1592
|
-
const dir = getTaskOutputsDir();
|
|
1593
|
-
if (existsSync3(dir)) return;
|
|
1594
|
-
mkdirSync3(dir, { recursive: true });
|
|
1595
|
-
}
|
|
1596
|
-
function touchTaskOutputFile(taskId) {
|
|
1597
|
-
ensureTaskOutputsDirExists();
|
|
1598
|
-
const filePath = getTaskOutputFilePath(taskId);
|
|
1599
|
-
if (!existsSync3(filePath)) {
|
|
1600
|
-
const parent = dirname2(filePath);
|
|
1601
|
-
if (!existsSync3(parent)) mkdirSync3(parent, { recursive: true });
|
|
1602
|
-
writeFileSync2(filePath, "", "utf8");
|
|
1603
|
-
}
|
|
1604
|
-
return filePath;
|
|
1605
|
-
}
|
|
1606
|
-
function appendTaskOutput(taskId, chunk) {
|
|
1607
|
-
try {
|
|
1608
|
-
ensureTaskOutputsDirExists();
|
|
1609
|
-
appendFileSync(getTaskOutputFilePath(taskId), chunk, "utf8");
|
|
1610
|
-
} catch {
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
function readTaskOutput(taskId) {
|
|
1614
|
-
try {
|
|
1615
|
-
const filePath = getTaskOutputFilePath(taskId);
|
|
1616
|
-
if (!existsSync3(filePath)) return "";
|
|
1617
|
-
return readFileSync3(filePath, "utf8");
|
|
1618
|
-
} catch {
|
|
1619
|
-
return "";
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
// src/utils/bun/shell.ts
|
|
1624
|
-
function whichSync(bin) {
|
|
1625
|
-
try {
|
|
1626
|
-
return which.sync(bin, { nothrow: true }) ?? null;
|
|
1627
|
-
} catch {
|
|
1628
|
-
return null;
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
function whichOrSelf(bin) {
|
|
1632
|
-
return whichSync(bin) ?? bin;
|
|
1633
|
-
}
|
|
1634
|
-
function spawnWithExited(options) {
|
|
1635
|
-
const child = spawn(options.cmd[0], options.cmd.slice(1), {
|
|
1636
|
-
cwd: options.cwd,
|
|
1637
|
-
env: options.env ?? process.env,
|
|
1638
|
-
stdio: ["inherit", "pipe", "pipe"],
|
|
1639
|
-
windowsHide: true
|
|
1640
|
-
});
|
|
1641
|
-
child.exited = new Promise((resolve3) => {
|
|
1642
|
-
const done = () => resolve3();
|
|
1643
|
-
child.once("exit", done);
|
|
1644
|
-
child.once("error", done);
|
|
1645
|
-
});
|
|
1646
|
-
return child;
|
|
1647
|
-
}
|
|
1648
|
-
function maybeAnnotateMacosSandboxStderr(stderr, sandbox) {
|
|
1649
|
-
if (!stderr) return stderr;
|
|
1650
|
-
if (!sandbox || sandbox.enabled !== true) return stderr;
|
|
1651
|
-
const platform = sandbox.__platformOverride ?? process.platform;
|
|
1652
|
-
if (platform !== "darwin") return stderr;
|
|
1653
|
-
if (stderr.includes("[sandbox]")) return stderr;
|
|
1654
|
-
const lower = stderr.toLowerCase();
|
|
1655
|
-
const looksLikeSandboxViolation = stderr.includes("KODE_SANDBOX") || lower.includes("sandbox-exec") && (lower.includes("deny") || lower.includes("operation not permitted")) || lower.includes("operation not permitted") && lower.includes("sandbox");
|
|
1656
|
-
if (!looksLikeSandboxViolation) return stderr;
|
|
1657
|
-
return [
|
|
1658
|
-
stderr.trimEnd(),
|
|
1659
|
-
"",
|
|
1660
|
-
"[sandbox] This failure looks like a macOS sandbox denial. Adjust sandbox settings (e.g. /sandbox or .kode/settings.json) to grant the minimal required access."
|
|
1661
|
-
].join("\n");
|
|
1662
|
-
}
|
|
1663
|
-
function hasGlobPattern(value) {
|
|
1664
|
-
return value.includes("*") || value.includes("?") || value.includes("[") || value.includes("]");
|
|
1665
|
-
}
|
|
1666
|
-
function normalizeLinuxSandboxPath(input, options) {
|
|
1667
|
-
const cwd2 = options?.cwd ?? process.cwd();
|
|
1668
|
-
const homeDir = options?.homeDir ?? homedir2();
|
|
1669
|
-
let resolved = input;
|
|
1670
|
-
if (input === "~") resolved = homeDir;
|
|
1671
|
-
else if (input.startsWith("~/")) resolved = homeDir + input.slice(1);
|
|
1672
|
-
else if (input.startsWith("./") || input.startsWith("../"))
|
|
1673
|
-
resolved = resolve2(cwd2, input);
|
|
1674
|
-
else if (!isAbsolute2(input)) resolved = resolve2(cwd2, input);
|
|
1675
|
-
if (hasGlobPattern(resolved)) {
|
|
1676
|
-
const prefix = resolved.split(/[*?[\]]/)[0];
|
|
1677
|
-
if (prefix && prefix !== "/") {
|
|
1678
|
-
const dir = prefix.endsWith("/") ? prefix.slice(0, -1) : dirname3(prefix);
|
|
1679
|
-
try {
|
|
1680
|
-
const real = realpathSync2(dir);
|
|
1681
|
-
const suffix = resolved.slice(dir.length);
|
|
1682
|
-
return real + suffix;
|
|
1683
|
-
} catch {
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
return resolved;
|
|
1687
|
-
}
|
|
1688
|
-
try {
|
|
1689
|
-
resolved = realpathSync2(resolved);
|
|
1690
|
-
} catch {
|
|
1691
|
-
}
|
|
1692
|
-
return resolved;
|
|
1693
|
-
}
|
|
1694
|
-
function buildLinuxBwrapFilesystemArgs(options) {
|
|
1695
|
-
const cwd2 = options.cwd ?? process.cwd();
|
|
1696
|
-
const homeDir = options.homeDir ?? homedir2();
|
|
1697
|
-
const args = [];
|
|
1698
|
-
const writeConfig = options.writeConfig;
|
|
1699
|
-
if (writeConfig) {
|
|
1700
|
-
args.push("--ro-bind", "/", "/");
|
|
1701
|
-
const allowedRoots = [];
|
|
1702
|
-
if (existsSync4("/tmp/kode")) {
|
|
1703
|
-
args.push("--bind", "/tmp/kode", "/tmp/kode");
|
|
1704
|
-
allowedRoots.push("/tmp/kode");
|
|
1705
|
-
}
|
|
1706
|
-
for (const raw of writeConfig.allowOnly ?? []) {
|
|
1707
|
-
const resolved = normalizeLinuxSandboxPath(raw, { cwd: cwd2, homeDir });
|
|
1708
|
-
if (resolved.startsWith("/dev/")) continue;
|
|
1709
|
-
if (!existsSync4(resolved)) continue;
|
|
1710
|
-
args.push("--bind", resolved, resolved);
|
|
1711
|
-
allowedRoots.push(resolved);
|
|
1712
|
-
}
|
|
1713
|
-
const denyWithinAllow = [
|
|
1714
|
-
...writeConfig.denyWithinAllow ?? [],
|
|
1715
|
-
...options.extraDenyWithinAllow ?? []
|
|
1716
|
-
];
|
|
1717
|
-
for (const raw of denyWithinAllow) {
|
|
1718
|
-
const resolved = normalizeLinuxSandboxPath(raw, { cwd: cwd2, homeDir });
|
|
1719
|
-
if (resolved.startsWith("/dev/")) continue;
|
|
1720
|
-
if (!existsSync4(resolved)) continue;
|
|
1721
|
-
const withinAllowed = allowedRoots.some(
|
|
1722
|
-
(root) => resolved === root || resolved.startsWith(root + "/")
|
|
1723
|
-
);
|
|
1724
|
-
if (!withinAllowed) continue;
|
|
1725
|
-
args.push("--ro-bind", resolved, resolved);
|
|
1726
|
-
}
|
|
1727
|
-
} else {
|
|
1728
|
-
args.push("--bind", "/", "/");
|
|
1729
|
-
}
|
|
1730
|
-
const denyRead = [...options.readConfig?.denyOnly ?? []];
|
|
1731
|
-
if (existsSync4("/etc/ssh/ssh_config.d"))
|
|
1732
|
-
denyRead.push("/etc/ssh/ssh_config.d");
|
|
1733
|
-
for (const raw of denyRead) {
|
|
1734
|
-
const resolved = normalizeLinuxSandboxPath(raw, { cwd: cwd2, homeDir });
|
|
1735
|
-
if (resolved.startsWith("/dev/")) continue;
|
|
1736
|
-
if (!existsSync4(resolved)) continue;
|
|
1737
|
-
if (statSync3(resolved).isDirectory()) args.push("--tmpfs", resolved);
|
|
1738
|
-
else args.push("--ro-bind", "/dev/null", resolved);
|
|
1739
|
-
}
|
|
1740
|
-
return args;
|
|
1741
|
-
}
|
|
1742
|
-
function buildLinuxBwrapCommand(options) {
|
|
1743
|
-
const args = [];
|
|
1744
|
-
args.push(
|
|
1745
|
-
"--die-with-parent",
|
|
1746
|
-
"--new-session",
|
|
1747
|
-
"--unshare-pid",
|
|
1748
|
-
"--unshare-uts",
|
|
1749
|
-
"--unshare-ipc"
|
|
1750
|
-
);
|
|
1751
|
-
if (options.needsNetworkRestriction) args.push("--unshare-net");
|
|
1752
|
-
args.push(
|
|
1753
|
-
...buildLinuxBwrapFilesystemArgs({
|
|
1754
|
-
cwd: options.cwd,
|
|
1755
|
-
homeDir: options.homeDir,
|
|
1756
|
-
readConfig: options.readConfig,
|
|
1757
|
-
writeConfig: options.writeConfig
|
|
1758
|
-
})
|
|
1759
|
-
);
|
|
1760
|
-
args.push(
|
|
1761
|
-
"--dev",
|
|
1762
|
-
"/dev",
|
|
1763
|
-
"--setenv",
|
|
1764
|
-
"SANDBOX_RUNTIME",
|
|
1765
|
-
"1",
|
|
1766
|
-
"--setenv",
|
|
1767
|
-
"TMPDIR",
|
|
1768
|
-
"/tmp/kode"
|
|
1769
|
-
);
|
|
1770
|
-
if (!options.enableWeakerNestedSandbox) args.push("--proc", "/proc");
|
|
1771
|
-
args.push("--", options.binShellPath, "-c", options.command);
|
|
1772
|
-
return [options.bwrapPath, ...args];
|
|
1773
|
-
}
|
|
1774
|
-
function buildSandboxEnvAssignments(options) {
|
|
1775
|
-
const httpProxyPort = options?.httpProxyPort;
|
|
1776
|
-
const socksProxyPort = options?.socksProxyPort;
|
|
1777
|
-
const platform = options?.platform ?? process.platform;
|
|
1778
|
-
const env2 = ["SANDBOX_RUNTIME=1", "TMPDIR=/tmp/kode"];
|
|
1779
|
-
if (!httpProxyPort && !socksProxyPort) return env2;
|
|
1780
|
-
const noProxy = [
|
|
1781
|
-
"localhost",
|
|
1782
|
-
"127.0.0.1",
|
|
1783
|
-
"::1",
|
|
1784
|
-
"*.local",
|
|
1785
|
-
".local",
|
|
1786
|
-
"169.254.0.0/16",
|
|
1787
|
-
"10.0.0.0/8",
|
|
1788
|
-
"172.16.0.0/12",
|
|
1789
|
-
"192.168.0.0/16"
|
|
1790
|
-
].join(",");
|
|
1791
|
-
env2.push(`NO_PROXY=${noProxy}`);
|
|
1792
|
-
env2.push(`no_proxy=${noProxy}`);
|
|
1793
|
-
if (httpProxyPort) {
|
|
1794
|
-
env2.push(`HTTP_PROXY=http://localhost:${httpProxyPort}`);
|
|
1795
|
-
env2.push(`HTTPS_PROXY=http://localhost:${httpProxyPort}`);
|
|
1796
|
-
env2.push(`http_proxy=http://localhost:${httpProxyPort}`);
|
|
1797
|
-
env2.push(`https_proxy=http://localhost:${httpProxyPort}`);
|
|
1798
|
-
}
|
|
1799
|
-
if (socksProxyPort) {
|
|
1800
|
-
env2.push(`ALL_PROXY=socks5h://localhost:${socksProxyPort}`);
|
|
1801
|
-
env2.push(`all_proxy=socks5h://localhost:${socksProxyPort}`);
|
|
1802
|
-
if (platform === "darwin") {
|
|
1803
|
-
env2.push(
|
|
1804
|
-
`GIT_SSH_COMMAND="ssh -o ProxyCommand='nc -X 5 -x localhost:${socksProxyPort} %h %p'"`
|
|
1805
|
-
);
|
|
1806
|
-
}
|
|
1807
|
-
env2.push(`FTP_PROXY=socks5h://localhost:${socksProxyPort}`);
|
|
1808
|
-
env2.push(`ftp_proxy=socks5h://localhost:${socksProxyPort}`);
|
|
1809
|
-
env2.push(`RSYNC_PROXY=localhost:${socksProxyPort}`);
|
|
1810
|
-
env2.push(
|
|
1811
|
-
`DOCKER_HTTP_PROXY=http://localhost:${httpProxyPort || socksProxyPort}`
|
|
1812
|
-
);
|
|
1813
|
-
env2.push(
|
|
1814
|
-
`DOCKER_HTTPS_PROXY=http://localhost:${httpProxyPort || socksProxyPort}`
|
|
1815
|
-
);
|
|
1816
|
-
if (httpProxyPort) {
|
|
1817
|
-
env2.push("CLOUDSDK_PROXY_TYPE=https");
|
|
1818
|
-
env2.push("CLOUDSDK_PROXY_ADDRESS=localhost");
|
|
1819
|
-
env2.push(`CLOUDSDK_PROXY_PORT=${httpProxyPort}`);
|
|
1820
|
-
}
|
|
1821
|
-
env2.push(`GRPC_PROXY=socks5h://localhost:${socksProxyPort}`);
|
|
1822
|
-
env2.push(`grpc_proxy=socks5h://localhost:${socksProxyPort}`);
|
|
1823
|
-
}
|
|
1824
|
-
return env2;
|
|
1825
|
-
}
|
|
1826
|
-
function escapeRegexForSandboxGlobPattern(pattern) {
|
|
1827
|
-
return "^" + pattern.replace(/[.^$+{}()|\\]/g, "\\$&").replace(/\[([^\]]*?)$/g, "\\[$1").replace(/\*\*\//g, "__GLOBSTAR_SLASH__").replace(/\*\*/g, "__GLOBSTAR__").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/__GLOBSTAR_SLASH__/g, "(.*/)?").replace(/__GLOBSTAR__/g, ".*") + "$";
|
|
1828
|
-
}
|
|
1829
|
-
function getMacosTmpDirWriteAllowPaths() {
|
|
1830
|
-
const tmpdirValue = process.env.TMPDIR;
|
|
1831
|
-
if (!tmpdirValue) return [];
|
|
1832
|
-
if (!tmpdirValue.match(/^\/(private\/)?var\/folders\/[^/]{2}\/[^/]+\/T\/?$/))
|
|
1833
|
-
return [];
|
|
1834
|
-
const base = tmpdirValue.replace(/\/T\/?$/, "");
|
|
1835
|
-
if (base.startsWith("/private/var/"))
|
|
1836
|
-
return [base, base.replace("/private", "")];
|
|
1837
|
-
if (base.startsWith("/var/")) return [base, "/private" + base];
|
|
1838
|
-
return [base];
|
|
1839
|
-
}
|
|
1840
|
-
function buildMacosSandboxDenyUnlinkRules(paths2, logTag) {
|
|
1841
|
-
const lines = [];
|
|
1842
|
-
for (const raw of paths2) {
|
|
1843
|
-
const normalized = normalizeLinuxSandboxPath(raw);
|
|
1844
|
-
if (hasGlobPattern(normalized)) {
|
|
1845
|
-
const regex = escapeRegexForSandboxGlobPattern(normalized);
|
|
1846
|
-
lines.push(
|
|
1847
|
-
"(deny file-write-unlink",
|
|
1848
|
-
` (regex ${JSON.stringify(regex)})`,
|
|
1849
|
-
` (with message "${logTag}"))`
|
|
1850
|
-
);
|
|
1851
|
-
const prefix = normalized.split(/[*?[\]]/)[0];
|
|
1852
|
-
if (prefix && prefix !== "/") {
|
|
1853
|
-
const literal = prefix.endsWith("/") ? prefix.slice(0, -1) : dirname3(prefix);
|
|
1854
|
-
lines.push(
|
|
1855
|
-
"(deny file-write-unlink",
|
|
1856
|
-
` (literal ${JSON.stringify(literal)})`,
|
|
1857
|
-
` (with message "${logTag}"))`
|
|
1858
|
-
);
|
|
1859
|
-
}
|
|
1860
|
-
continue;
|
|
1861
|
-
}
|
|
1862
|
-
lines.push(
|
|
1863
|
-
"(deny file-write-unlink",
|
|
1864
|
-
` (subpath ${JSON.stringify(normalized)})`,
|
|
1865
|
-
` (with message "${logTag}"))`
|
|
1866
|
-
);
|
|
1867
|
-
}
|
|
1868
|
-
return lines;
|
|
1869
|
-
}
|
|
1870
|
-
function buildMacosSandboxFileReadRules(readConfig, logTag) {
|
|
1871
|
-
if (!readConfig) return ["(allow file-read*)"];
|
|
1872
|
-
const lines = ["(allow file-read*)"];
|
|
1873
|
-
for (const raw of readConfig.denyOnly ?? []) {
|
|
1874
|
-
const normalized = normalizeLinuxSandboxPath(raw);
|
|
1875
|
-
if (hasGlobPattern(normalized)) {
|
|
1876
|
-
const regex = escapeRegexForSandboxGlobPattern(normalized);
|
|
1877
|
-
lines.push(
|
|
1878
|
-
"(deny file-read*",
|
|
1879
|
-
` (regex ${JSON.stringify(regex)})`,
|
|
1880
|
-
` (with message "${logTag}"))`
|
|
1881
|
-
);
|
|
1882
|
-
} else {
|
|
1883
|
-
lines.push(
|
|
1884
|
-
"(deny file-read*",
|
|
1885
|
-
` (subpath ${JSON.stringify(normalized)})`,
|
|
1886
|
-
` (with message "${logTag}"))`
|
|
1887
|
-
);
|
|
1888
|
-
}
|
|
1889
|
-
}
|
|
1890
|
-
lines.push(
|
|
1891
|
-
...buildMacosSandboxDenyUnlinkRules(readConfig.denyOnly ?? [], logTag)
|
|
1892
|
-
);
|
|
1893
|
-
return lines;
|
|
1894
|
-
}
|
|
1895
|
-
function buildMacosSandboxFileWriteRules(writeConfig, logTag) {
|
|
1896
|
-
if (!writeConfig) return ["(allow file-write*)"];
|
|
1897
|
-
const lines = [];
|
|
1898
|
-
lines.push(
|
|
1899
|
-
"(allow file-write*",
|
|
1900
|
-
` (literal "/dev/null")`,
|
|
1901
|
-
` (with message "${logTag}"))`
|
|
1902
|
-
);
|
|
1903
|
-
for (const raw of getMacosTmpDirWriteAllowPaths()) {
|
|
1904
|
-
const normalized = normalizeLinuxSandboxPath(raw);
|
|
1905
|
-
lines.push(
|
|
1906
|
-
"(allow file-write*",
|
|
1907
|
-
` (subpath ${JSON.stringify(normalized)})`,
|
|
1908
|
-
` (with message "${logTag}"))`
|
|
1909
|
-
);
|
|
1910
|
-
}
|
|
1911
|
-
for (const raw of writeConfig.allowOnly ?? []) {
|
|
1912
|
-
const normalized = normalizeLinuxSandboxPath(raw);
|
|
1913
|
-
if (hasGlobPattern(normalized)) {
|
|
1914
|
-
const regex = escapeRegexForSandboxGlobPattern(normalized);
|
|
1915
|
-
lines.push(
|
|
1916
|
-
"(allow file-write*",
|
|
1917
|
-
` (regex ${JSON.stringify(regex)})`,
|
|
1918
|
-
` (with message "${logTag}"))`
|
|
1919
|
-
);
|
|
1920
|
-
} else {
|
|
1921
|
-
lines.push(
|
|
1922
|
-
"(allow file-write*",
|
|
1923
|
-
` (subpath ${JSON.stringify(normalized)})`,
|
|
1924
|
-
` (with message "${logTag}"))`
|
|
1925
|
-
);
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
for (const raw of writeConfig.denyWithinAllow ?? []) {
|
|
1929
|
-
const normalized = normalizeLinuxSandboxPath(raw);
|
|
1930
|
-
if (hasGlobPattern(normalized)) {
|
|
1931
|
-
const regex = escapeRegexForSandboxGlobPattern(normalized);
|
|
1932
|
-
lines.push(
|
|
1933
|
-
"(deny file-write*",
|
|
1934
|
-
` (regex ${JSON.stringify(regex)})`,
|
|
1935
|
-
` (with message "${logTag}"))`
|
|
1936
|
-
);
|
|
1937
|
-
} else {
|
|
1938
|
-
lines.push(
|
|
1939
|
-
"(deny file-write*",
|
|
1940
|
-
` (subpath ${JSON.stringify(normalized)})`,
|
|
1941
|
-
` (with message "${logTag}"))`
|
|
1942
|
-
);
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
lines.push(
|
|
1946
|
-
...buildMacosSandboxDenyUnlinkRules(
|
|
1947
|
-
writeConfig.denyWithinAllow ?? [],
|
|
1948
|
-
logTag
|
|
1949
|
-
)
|
|
1950
|
-
);
|
|
1951
|
-
return lines;
|
|
1952
|
-
}
|
|
1953
|
-
function buildMacosSandboxExecCommand(options) {
|
|
1954
|
-
const logTag = "KODE_SANDBOX";
|
|
1955
|
-
const profileLines = [
|
|
1956
|
-
"(version 1)",
|
|
1957
|
-
`(deny default (with message "${logTag}"))`,
|
|
1958
|
-
"",
|
|
1959
|
-
"; Kode sandbox-exec profile (reference CLI compatible)",
|
|
1960
|
-
"",
|
|
1961
|
-
"(allow process*)",
|
|
1962
|
-
"(allow sysctl-read)",
|
|
1963
|
-
"(allow mach-lookup)",
|
|
1964
|
-
"",
|
|
1965
|
-
"; Network"
|
|
1966
|
-
];
|
|
1967
|
-
const allowUnixSockets = options.allowUnixSockets ?? [];
|
|
1968
|
-
if (!options.needsNetworkRestriction) {
|
|
1969
|
-
profileLines.push("(allow network*)");
|
|
1970
|
-
} else {
|
|
1971
|
-
if (options.allowLocalBinding) {
|
|
1972
|
-
profileLines.push('(allow network-bind (local ip "localhost:*"))');
|
|
1973
|
-
profileLines.push('(allow network-inbound (local ip "localhost:*"))');
|
|
1974
|
-
profileLines.push('(allow network-outbound (local ip "localhost:*"))');
|
|
1975
|
-
}
|
|
1976
|
-
if (options.allowAllUnixSockets) {
|
|
1977
|
-
profileLines.push('(allow network* (subpath "/"))');
|
|
1978
|
-
} else if (allowUnixSockets.length > 0) {
|
|
1979
|
-
for (const socketPath of allowUnixSockets) {
|
|
1980
|
-
const normalized = normalizeLinuxSandboxPath(socketPath);
|
|
1981
|
-
profileLines.push(
|
|
1982
|
-
`(allow network* (subpath ${JSON.stringify(normalized)}))`
|
|
1983
|
-
);
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
if (options.httpProxyPort !== void 0) {
|
|
1987
|
-
profileLines.push(
|
|
1988
|
-
`(allow network-bind (local ip "localhost:${options.httpProxyPort}"))`
|
|
1989
|
-
);
|
|
1990
|
-
profileLines.push(
|
|
1991
|
-
`(allow network-inbound (local ip "localhost:${options.httpProxyPort}"))`
|
|
1992
|
-
);
|
|
1993
|
-
profileLines.push(
|
|
1994
|
-
`(allow network-outbound (remote ip "localhost:${options.httpProxyPort}"))`
|
|
1995
|
-
);
|
|
1996
|
-
}
|
|
1997
|
-
if (options.socksProxyPort !== void 0) {
|
|
1998
|
-
profileLines.push(
|
|
1999
|
-
`(allow network-bind (local ip "localhost:${options.socksProxyPort}"))`
|
|
2000
|
-
);
|
|
2001
|
-
profileLines.push(
|
|
2002
|
-
`(allow network-inbound (local ip "localhost:${options.socksProxyPort}"))`
|
|
2003
|
-
);
|
|
2004
|
-
profileLines.push(
|
|
2005
|
-
`(allow network-outbound (remote ip "localhost:${options.socksProxyPort}"))`
|
|
2006
|
-
);
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
profileLines.push("");
|
|
2010
|
-
profileLines.push("; File read");
|
|
2011
|
-
profileLines.push(
|
|
2012
|
-
...buildMacosSandboxFileReadRules(options.readConfig, logTag)
|
|
2013
|
-
);
|
|
2014
|
-
profileLines.push("");
|
|
2015
|
-
profileLines.push("; File write");
|
|
2016
|
-
profileLines.push(
|
|
2017
|
-
...buildMacosSandboxFileWriteRules(options.writeConfig, logTag)
|
|
2018
|
-
);
|
|
2019
|
-
const profile = profileLines.join("\n");
|
|
2020
|
-
const envAssignments = buildSandboxEnvAssignments({
|
|
2021
|
-
httpProxyPort: options.httpProxyPort,
|
|
2022
|
-
socksProxyPort: options.socksProxyPort,
|
|
2023
|
-
platform: "darwin"
|
|
2024
|
-
});
|
|
2025
|
-
const envPrefix = envAssignments.length ? `export ${envAssignments.join(" ")} && ` : "";
|
|
2026
|
-
return [
|
|
2027
|
-
options.sandboxExecPath,
|
|
2028
|
-
"-p",
|
|
2029
|
-
profile,
|
|
2030
|
-
options.binShellPath,
|
|
2031
|
-
"-c",
|
|
2032
|
-
`${envPrefix}${options.command}`
|
|
2033
|
-
];
|
|
2034
|
-
}
|
|
2035
|
-
function renderBackgroundShellStatusAttachment(attachment) {
|
|
2036
|
-
const parts = [];
|
|
2037
|
-
if (attachment.stdoutLineDelta > 0) {
|
|
2038
|
-
const n = attachment.stdoutLineDelta;
|
|
2039
|
-
parts.push(`${n} line${n > 1 ? "s" : ""} of stdout`);
|
|
2040
|
-
}
|
|
2041
|
-
if (attachment.stderrLineDelta > 0) {
|
|
2042
|
-
const n = attachment.stderrLineDelta;
|
|
2043
|
-
parts.push(`${n} line${n > 1 ? "s" : ""} of stderr`);
|
|
2044
|
-
}
|
|
2045
|
-
if (parts.length === 0) return "";
|
|
2046
|
-
return `Background bash ${attachment.taskId} has new output: ${parts.join(", ")}. Read ${attachment.outputFile} to see output.`;
|
|
2047
|
-
}
|
|
2048
|
-
function renderBashNotification(notification) {
|
|
2049
|
-
const status = notification.status;
|
|
2050
|
-
const exitCode = notification.exitCode;
|
|
2051
|
-
const summarySuffix = status === "completed" ? `completed${exitCode !== void 0 ? ` (exit code ${exitCode})` : ""}` : status === "failed" ? `failed${exitCode !== void 0 ? ` with exit code ${exitCode}` : ""}` : "was killed";
|
|
2052
|
-
return [
|
|
2053
|
-
"<bash-notification>",
|
|
2054
|
-
`<shell-id>${notification.taskId}</shell-id>`,
|
|
2055
|
-
`<output-file>${notification.outputFile}</output-file>`,
|
|
2056
|
-
`<status>${status}</status>`,
|
|
2057
|
-
`<summary>Background command "${notification.description}" ${summarySuffix}.</summary>`,
|
|
2058
|
-
"Read the output file to retrieve the output.",
|
|
2059
|
-
"</bash-notification>"
|
|
2060
|
-
].join("\n");
|
|
2061
|
-
}
|
|
2062
|
-
var BunShell = class _BunShell {
|
|
2063
|
-
cwd;
|
|
2064
|
-
isAlive = true;
|
|
2065
|
-
currentProcess = null;
|
|
2066
|
-
abortController = null;
|
|
2067
|
-
backgroundProcesses = /* @__PURE__ */ new Map();
|
|
2068
|
-
constructor(cwd2) {
|
|
2069
|
-
this.cwd = cwd2;
|
|
2070
|
-
}
|
|
2071
|
-
static instance = null;
|
|
2072
|
-
static restart() {
|
|
2073
|
-
if (_BunShell.instance) {
|
|
2074
|
-
_BunShell.instance.close();
|
|
2075
|
-
_BunShell.instance = null;
|
|
2076
|
-
}
|
|
2077
|
-
}
|
|
2078
|
-
static getInstance() {
|
|
2079
|
-
if (!_BunShell.instance || !_BunShell.instance.isAlive) {
|
|
2080
|
-
_BunShell.instance = new _BunShell(process.cwd());
|
|
2081
|
-
}
|
|
2082
|
-
return _BunShell.instance;
|
|
2083
|
-
}
|
|
2084
|
-
static getShellCmdForPlatform(platform, command, env2 = process.env) {
|
|
2085
|
-
if (platform === "win32") {
|
|
2086
|
-
const comspec = typeof env2.ComSpec === "string" && env2.ComSpec.length > 0 ? env2.ComSpec : "cmd";
|
|
2087
|
-
return [comspec, "/c", command];
|
|
2088
|
-
}
|
|
2089
|
-
const sh = existsSync4("/bin/sh") ? "/bin/sh" : "sh";
|
|
2090
|
-
return [sh, "-c", command];
|
|
2091
|
-
}
|
|
2092
|
-
getShellCmd(command) {
|
|
2093
|
-
return _BunShell.getShellCmdForPlatform(
|
|
2094
|
-
process.platform,
|
|
2095
|
-
command,
|
|
2096
|
-
process.env
|
|
2097
|
-
);
|
|
2098
|
-
}
|
|
2099
|
-
buildSandboxCmd(command, sandbox) {
|
|
2100
|
-
if (!sandbox.enabled) return null;
|
|
2101
|
-
const platform = sandbox.__platformOverride ?? process.platform;
|
|
2102
|
-
const needsNetworkRestriction = sandbox.needsNetworkRestriction !== void 0 ? sandbox.needsNetworkRestriction : sandbox.allowNetwork === true ? false : true;
|
|
2103
|
-
const writeConfig = sandbox.writeConfig ?? (sandbox.writableRoots && sandbox.writableRoots.length > 0 ? { allowOnly: sandbox.writableRoots.filter(Boolean) } : void 0);
|
|
2104
|
-
const readConfig = sandbox.readConfig;
|
|
2105
|
-
const hasReadRestrictions = (readConfig?.denyOnly?.length ?? 0) > 0;
|
|
2106
|
-
const hasWriteRestrictions = writeConfig !== void 0;
|
|
2107
|
-
const hasNetworkRestrictions = needsNetworkRestriction === true;
|
|
2108
|
-
if (!hasReadRestrictions && !hasWriteRestrictions && !hasNetworkRestrictions) {
|
|
2109
|
-
return null;
|
|
2110
|
-
}
|
|
2111
|
-
const binShell = sandbox.binShell ?? (whichSync("bash") ? "bash" : "sh");
|
|
2112
|
-
const binShellPath = whichOrSelf(binShell);
|
|
2113
|
-
const cwd2 = sandbox.chdir || this.cwd;
|
|
2114
|
-
if (platform === "linux") {
|
|
2115
|
-
const bwrapPath = sandbox.__bwrapPathOverride !== void 0 ? sandbox.__bwrapPathOverride : whichSync("bwrap") ?? whichSync("bubblewrap");
|
|
2116
|
-
if (!bwrapPath) {
|
|
2117
|
-
return null;
|
|
2118
|
-
}
|
|
2119
|
-
try {
|
|
2120
|
-
mkdirSync4("/tmp/kode", { recursive: true });
|
|
2121
|
-
} catch {
|
|
2122
|
-
}
|
|
2123
|
-
const cmd = buildLinuxBwrapCommand({
|
|
2124
|
-
bwrapPath,
|
|
2125
|
-
command,
|
|
2126
|
-
needsNetworkRestriction,
|
|
2127
|
-
readConfig,
|
|
2128
|
-
writeConfig,
|
|
2129
|
-
enableWeakerNestedSandbox: sandbox.enableWeakerNestedSandbox,
|
|
2130
|
-
binShellPath,
|
|
2131
|
-
cwd: cwd2
|
|
2132
|
-
});
|
|
2133
|
-
return { cmd };
|
|
2134
|
-
}
|
|
2135
|
-
if (platform === "darwin") {
|
|
2136
|
-
const sandboxExecPath = sandbox.__sandboxExecPathOverride !== void 0 ? sandbox.__sandboxExecPathOverride : existsSync4("/usr/bin/sandbox-exec") ? "/usr/bin/sandbox-exec" : whichSync("sandbox-exec");
|
|
2137
|
-
if (!sandboxExecPath) {
|
|
2138
|
-
return null;
|
|
2139
|
-
}
|
|
2140
|
-
try {
|
|
2141
|
-
mkdirSync4("/tmp/kode", { recursive: true });
|
|
2142
|
-
} catch {
|
|
2143
|
-
}
|
|
2144
|
-
try {
|
|
2145
|
-
mkdirSync4("/private/tmp/kode", { recursive: true });
|
|
2146
|
-
} catch {
|
|
2147
|
-
}
|
|
2148
|
-
return {
|
|
2149
|
-
cmd: buildMacosSandboxExecCommand({
|
|
2150
|
-
sandboxExecPath,
|
|
2151
|
-
binShellPath,
|
|
2152
|
-
command,
|
|
2153
|
-
needsNetworkRestriction,
|
|
2154
|
-
httpProxyPort: sandbox.httpProxyPort,
|
|
2155
|
-
socksProxyPort: sandbox.socksProxyPort,
|
|
2156
|
-
allowUnixSockets: sandbox.allowUnixSockets,
|
|
2157
|
-
allowAllUnixSockets: sandbox.allowAllUnixSockets,
|
|
2158
|
-
allowLocalBinding: sandbox.allowLocalBinding,
|
|
2159
|
-
readConfig,
|
|
2160
|
-
writeConfig
|
|
2161
|
-
})
|
|
2162
|
-
};
|
|
2163
|
-
}
|
|
2164
|
-
return null;
|
|
2165
|
-
}
|
|
2166
|
-
isSandboxInitFailure(stderr) {
|
|
2167
|
-
const s = stderr.toLowerCase();
|
|
2168
|
-
return s.includes("bwrap:") || s.includes("bubblewrap") || s.includes("namespace") && s.includes("failed");
|
|
2169
|
-
}
|
|
2170
|
-
startStreamReader(stream, append) {
|
|
2171
|
-
if (!stream) return;
|
|
2172
|
-
try {
|
|
2173
|
-
;
|
|
2174
|
-
stream.setEncoding?.("utf8");
|
|
2175
|
-
} catch {
|
|
2176
|
-
}
|
|
2177
|
-
stream.on("data", (chunk) => {
|
|
2178
|
-
append(
|
|
2179
|
-
typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk)
|
|
2180
|
-
);
|
|
2181
|
-
});
|
|
2182
|
-
stream.on("error", (err) => {
|
|
2183
|
-
logError(`Stream read error: ${err}`);
|
|
2184
|
-
});
|
|
2185
|
-
}
|
|
2186
|
-
createCancellableTextCollector(stream, options) {
|
|
2187
|
-
let text = "";
|
|
2188
|
-
const collectText = options?.collectText !== false;
|
|
2189
|
-
if (!stream) {
|
|
2190
|
-
return {
|
|
2191
|
-
getText: () => text,
|
|
2192
|
-
done: Promise.resolve(),
|
|
2193
|
-
cancel: async () => {
|
|
2194
|
-
}
|
|
2195
|
-
};
|
|
2196
|
-
}
|
|
2197
|
-
let cancelled = false;
|
|
2198
|
-
let resolveDone = null;
|
|
2199
|
-
const done = new Promise((resolve3) => {
|
|
2200
|
-
resolveDone = resolve3;
|
|
2201
|
-
});
|
|
2202
|
-
const finish = () => {
|
|
2203
|
-
if (!resolveDone) return;
|
|
2204
|
-
resolveDone();
|
|
2205
|
-
resolveDone = null;
|
|
2206
|
-
};
|
|
2207
|
-
const onData = (chunk) => {
|
|
2208
|
-
if (cancelled) return;
|
|
2209
|
-
const s = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk);
|
|
2210
|
-
if (collectText) text += s;
|
|
2211
|
-
options?.onChunk?.(s);
|
|
2212
|
-
};
|
|
2213
|
-
const onEnd = () => {
|
|
2214
|
-
cleanup();
|
|
2215
|
-
finish();
|
|
2216
|
-
};
|
|
2217
|
-
const onClose = () => {
|
|
2218
|
-
cleanup();
|
|
2219
|
-
finish();
|
|
2220
|
-
};
|
|
2221
|
-
const cleanup = () => {
|
|
2222
|
-
stream.off("data", onData);
|
|
2223
|
-
stream.off("end", onEnd);
|
|
2224
|
-
stream.off("close", onClose);
|
|
2225
|
-
stream.off("error", onError);
|
|
2226
|
-
};
|
|
2227
|
-
const onError = (err) => {
|
|
2228
|
-
if (!cancelled) {
|
|
2229
|
-
logError(`Stream read error: ${err}`);
|
|
2230
|
-
}
|
|
2231
|
-
cleanup();
|
|
2232
|
-
finish();
|
|
2233
|
-
};
|
|
2234
|
-
try {
|
|
2235
|
-
;
|
|
2236
|
-
stream.setEncoding?.("utf8");
|
|
2237
|
-
} catch {
|
|
2238
|
-
}
|
|
2239
|
-
stream.on("data", onData);
|
|
2240
|
-
stream.once("end", onEnd);
|
|
2241
|
-
stream.once("close", onClose);
|
|
2242
|
-
stream.once("error", onError);
|
|
2243
|
-
return {
|
|
2244
|
-
getText: () => text,
|
|
2245
|
-
done,
|
|
2246
|
-
cancel: async () => {
|
|
2247
|
-
if (cancelled) return;
|
|
2248
|
-
cancelled = true;
|
|
2249
|
-
cleanup();
|
|
2250
|
-
finish();
|
|
2251
|
-
}
|
|
2252
|
-
};
|
|
2253
|
-
}
|
|
2254
|
-
static makeBackgroundTaskId() {
|
|
2255
|
-
return `b${randomUUID2().replace(/-/g, "").slice(0, 6)}`;
|
|
2256
|
-
}
|
|
2257
|
-
execPromotable(command, abortSignal, timeout, options) {
|
|
2258
|
-
const DEFAULT_TIMEOUT = 12e4;
|
|
2259
|
-
const commandTimeout = timeout ?? DEFAULT_TIMEOUT;
|
|
2260
|
-
const startedAt = Date.now();
|
|
2261
|
-
const sandbox = options?.sandbox;
|
|
2262
|
-
const shouldAttemptSandbox = sandbox?.enabled === true;
|
|
2263
|
-
const executionCwd = shouldAttemptSandbox && sandbox?.chdir ? sandbox.chdir : this.cwd;
|
|
2264
|
-
if (abortSignal?.aborted) {
|
|
2265
|
-
return {
|
|
2266
|
-
get status() {
|
|
2267
|
-
return "killed";
|
|
2268
|
-
},
|
|
2269
|
-
background: () => null,
|
|
2270
|
-
kill: () => {
|
|
2271
|
-
},
|
|
2272
|
-
result: Promise.resolve({
|
|
2273
|
-
stdout: "",
|
|
2274
|
-
stderr: "Command aborted before execution",
|
|
2275
|
-
code: 145,
|
|
2276
|
-
interrupted: true
|
|
2277
|
-
})
|
|
2278
|
-
};
|
|
2279
|
-
}
|
|
2280
|
-
const sandboxCmd = shouldAttemptSandbox ? this.buildSandboxCmd(command, sandbox) : null;
|
|
2281
|
-
if (shouldAttemptSandbox && sandbox?.require && !sandboxCmd) {
|
|
2282
|
-
return {
|
|
2283
|
-
get status() {
|
|
2284
|
-
return "killed";
|
|
2285
|
-
},
|
|
2286
|
-
background: () => null,
|
|
2287
|
-
kill: () => {
|
|
2288
|
-
},
|
|
2289
|
-
result: Promise.resolve({
|
|
2290
|
-
stdout: "",
|
|
2291
|
-
stderr: "System sandbox is required but unavailable (missing bubblewrap or unsupported platform).",
|
|
2292
|
-
code: 2,
|
|
2293
|
-
interrupted: false
|
|
2294
|
-
})
|
|
2295
|
-
};
|
|
2296
|
-
}
|
|
2297
|
-
const cmdToRun = sandboxCmd ? sandboxCmd.cmd : this.getShellCmd(command);
|
|
2298
|
-
const internalAbortController = new AbortController();
|
|
2299
|
-
this.abortController = internalAbortController;
|
|
2300
|
-
let status = "running";
|
|
2301
|
-
let backgroundProcess = null;
|
|
2302
|
-
let backgroundTaskId = null;
|
|
2303
|
-
let stdout = "";
|
|
2304
|
-
let stderr = "";
|
|
2305
|
-
let wasAborted = false;
|
|
2306
|
-
let wasBackgrounded = false;
|
|
2307
|
-
let timeoutHandle = null;
|
|
2308
|
-
let timedOut = false;
|
|
2309
|
-
let onTimeoutCb = null;
|
|
2310
|
-
const countNonEmptyLines = (chunk) => chunk.split("\n").filter((line) => line.length > 0).length;
|
|
2311
|
-
const spawnedProcess = spawnWithExited({ cmd: cmdToRun, cwd: executionCwd });
|
|
2312
|
-
this.currentProcess = spawnedProcess;
|
|
2313
|
-
const onAbort = () => {
|
|
2314
|
-
if (status === "backgrounded") return;
|
|
2315
|
-
wasAborted = true;
|
|
2316
|
-
try {
|
|
2317
|
-
internalAbortController.abort();
|
|
2318
|
-
} catch {
|
|
2319
|
-
}
|
|
2320
|
-
try {
|
|
2321
|
-
spawnedProcess.kill();
|
|
2322
|
-
} catch {
|
|
2323
|
-
}
|
|
2324
|
-
if (backgroundProcess) backgroundProcess.interrupted = true;
|
|
2325
|
-
};
|
|
2326
|
-
const clearForegroundGuards = () => {
|
|
2327
|
-
if (timeoutHandle) {
|
|
2328
|
-
clearTimeout(timeoutHandle);
|
|
2329
|
-
timeoutHandle = null;
|
|
2330
|
-
}
|
|
2331
|
-
if (abortSignal) {
|
|
2332
|
-
abortSignal.removeEventListener("abort", onAbort);
|
|
2333
|
-
}
|
|
2334
|
-
};
|
|
2335
|
-
if (abortSignal) {
|
|
2336
|
-
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
2337
|
-
if (abortSignal.aborted) onAbort();
|
|
2338
|
-
}
|
|
2339
|
-
const stdoutCollector = this.createCancellableTextCollector(
|
|
2340
|
-
spawnedProcess.stdout,
|
|
2341
|
-
{
|
|
2342
|
-
collectText: false,
|
|
2343
|
-
onChunk: (chunk) => {
|
|
2344
|
-
stdout += chunk;
|
|
2345
|
-
options?.onStdoutChunk?.(chunk);
|
|
2346
|
-
if (backgroundProcess) {
|
|
2347
|
-
backgroundProcess.stdout = stdout;
|
|
2348
|
-
appendTaskOutput(backgroundProcess.id, chunk);
|
|
2349
|
-
backgroundProcess.stdoutLineCount += countNonEmptyLines(chunk);
|
|
2350
|
-
}
|
|
2351
|
-
}
|
|
2352
|
-
}
|
|
2353
|
-
);
|
|
2354
|
-
const stderrCollector = this.createCancellableTextCollector(
|
|
2355
|
-
spawnedProcess.stderr,
|
|
2356
|
-
{
|
|
2357
|
-
collectText: false,
|
|
2358
|
-
onChunk: (chunk) => {
|
|
2359
|
-
stderr += chunk;
|
|
2360
|
-
options?.onStderrChunk?.(chunk);
|
|
2361
|
-
if (backgroundProcess) {
|
|
2362
|
-
backgroundProcess.stderr = stderr;
|
|
2363
|
-
appendTaskOutput(backgroundProcess.id, chunk);
|
|
2364
|
-
backgroundProcess.stderrLineCount += countNonEmptyLines(chunk);
|
|
2365
|
-
}
|
|
2366
|
-
}
|
|
2367
|
-
}
|
|
2368
|
-
);
|
|
2369
|
-
timeoutHandle = setTimeout(() => {
|
|
2370
|
-
if (status !== "running") return;
|
|
2371
|
-
if (onTimeoutCb) {
|
|
2372
|
-
onTimeoutCb(background);
|
|
2373
|
-
return;
|
|
2374
|
-
}
|
|
2375
|
-
timedOut = true;
|
|
2376
|
-
try {
|
|
2377
|
-
spawnedProcess.kill();
|
|
2378
|
-
} catch {
|
|
2379
|
-
}
|
|
2380
|
-
try {
|
|
2381
|
-
internalAbortController.abort();
|
|
2382
|
-
} catch {
|
|
2383
|
-
}
|
|
2384
|
-
}, commandTimeout);
|
|
2385
|
-
const background = (bashId) => {
|
|
2386
|
-
if (backgroundTaskId) return { bashId: backgroundTaskId };
|
|
2387
|
-
if (status !== "running") return null;
|
|
2388
|
-
backgroundTaskId = bashId ?? _BunShell.makeBackgroundTaskId();
|
|
2389
|
-
const outputFile = touchTaskOutputFile(backgroundTaskId);
|
|
2390
|
-
if (stdout) appendTaskOutput(backgroundTaskId, stdout);
|
|
2391
|
-
if (stderr) appendTaskOutput(backgroundTaskId, stderr);
|
|
2392
|
-
status = "backgrounded";
|
|
2393
|
-
wasBackgrounded = true;
|
|
2394
|
-
clearForegroundGuards();
|
|
2395
|
-
backgroundProcess = {
|
|
2396
|
-
id: backgroundTaskId,
|
|
2397
|
-
command,
|
|
2398
|
-
stdout,
|
|
2399
|
-
stderr,
|
|
2400
|
-
stdoutCursor: 0,
|
|
2401
|
-
stderrCursor: 0,
|
|
2402
|
-
stdoutLineCount: countNonEmptyLines(stdout),
|
|
2403
|
-
stderrLineCount: countNonEmptyLines(stderr),
|
|
2404
|
-
lastReportedStdoutLines: 0,
|
|
2405
|
-
lastReportedStderrLines: 0,
|
|
2406
|
-
code: null,
|
|
2407
|
-
interrupted: false,
|
|
2408
|
-
killed: false,
|
|
2409
|
-
timedOut: false,
|
|
2410
|
-
completionStatusSentInAttachment: false,
|
|
2411
|
-
notified: false,
|
|
2412
|
-
startedAt,
|
|
2413
|
-
timeoutAt: Number.POSITIVE_INFINITY,
|
|
2414
|
-
process: spawnedProcess,
|
|
2415
|
-
abortController: internalAbortController,
|
|
2416
|
-
timeoutHandle: null,
|
|
2417
|
-
cwd: executionCwd,
|
|
2418
|
-
outputFile
|
|
2419
|
-
};
|
|
2420
|
-
this.backgroundProcesses.set(backgroundTaskId, backgroundProcess);
|
|
2421
|
-
this.currentProcess = null;
|
|
2422
|
-
this.abortController = null;
|
|
2423
|
-
return { bashId: backgroundTaskId };
|
|
2424
|
-
};
|
|
2425
|
-
const kill = () => {
|
|
2426
|
-
status = "killed";
|
|
2427
|
-
try {
|
|
2428
|
-
spawnedProcess.kill();
|
|
2429
|
-
} catch {
|
|
2430
|
-
}
|
|
2431
|
-
try {
|
|
2432
|
-
internalAbortController.abort();
|
|
2433
|
-
} catch {
|
|
2434
|
-
}
|
|
2435
|
-
if (backgroundProcess) {
|
|
2436
|
-
backgroundProcess.interrupted = true;
|
|
2437
|
-
backgroundProcess.killed = true;
|
|
2438
|
-
}
|
|
2439
|
-
};
|
|
2440
|
-
const result = (async () => {
|
|
2441
|
-
try {
|
|
2442
|
-
await spawnedProcess.exited;
|
|
2443
|
-
if (status === "running" || status === "backgrounded")
|
|
2444
|
-
status = "completed";
|
|
2445
|
-
if (backgroundProcess) {
|
|
2446
|
-
backgroundProcess.code = spawnedProcess.exitCode ?? 0;
|
|
2447
|
-
backgroundProcess.interrupted = backgroundProcess.interrupted || wasAborted || internalAbortController.signal.aborted;
|
|
2448
|
-
}
|
|
2449
|
-
if (!wasBackgrounded) {
|
|
2450
|
-
await Promise.race([
|
|
2451
|
-
Promise.allSettled([stdoutCollector.done, stderrCollector.done]),
|
|
2452
|
-
new Promise((resolve3) => setTimeout(resolve3, 250))
|
|
2453
|
-
]);
|
|
2454
|
-
await Promise.allSettled([
|
|
2455
|
-
stdoutCollector.cancel(),
|
|
2456
|
-
stderrCollector.cancel()
|
|
2457
|
-
]);
|
|
2458
|
-
}
|
|
2459
|
-
const interrupted = wasAborted || abortSignal?.aborted === true || internalAbortController.signal.aborted === true || timedOut;
|
|
2460
|
-
let code = spawnedProcess.exitCode;
|
|
2461
|
-
if (!Number.isFinite(code)) {
|
|
2462
|
-
code = interrupted ? 143 : 0;
|
|
2463
|
-
}
|
|
2464
|
-
const stderrWithTimeout = timedOut ? [`Command timed out`, stderr].filter(Boolean).join("\n") : stderr;
|
|
2465
|
-
const stderrAnnotated = sandboxCmd ? maybeAnnotateMacosSandboxStderr(stderrWithTimeout, sandbox) : stderrWithTimeout;
|
|
2466
|
-
return {
|
|
2467
|
-
stdout,
|
|
2468
|
-
stderr: stderrAnnotated,
|
|
2469
|
-
code,
|
|
2470
|
-
interrupted
|
|
2471
|
-
};
|
|
2472
|
-
} finally {
|
|
2473
|
-
clearForegroundGuards();
|
|
2474
|
-
if (this.currentProcess === spawnedProcess) {
|
|
2475
|
-
this.currentProcess = null;
|
|
2476
|
-
this.abortController = null;
|
|
2477
|
-
}
|
|
2478
|
-
}
|
|
2479
|
-
})();
|
|
2480
|
-
const execHandle = {
|
|
2481
|
-
get status() {
|
|
2482
|
-
return status;
|
|
2483
|
-
},
|
|
2484
|
-
background,
|
|
2485
|
-
kill,
|
|
2486
|
-
result
|
|
2487
|
-
};
|
|
2488
|
-
execHandle.onTimeout = (cb) => {
|
|
2489
|
-
onTimeoutCb = cb;
|
|
2490
|
-
};
|
|
2491
|
-
result.then((r) => {
|
|
2492
|
-
if (!backgroundProcess || !backgroundTaskId) return;
|
|
2493
|
-
backgroundProcess.code = r.code;
|
|
2494
|
-
backgroundProcess.interrupted = r.interrupted;
|
|
2495
|
-
}).catch(() => {
|
|
2496
|
-
if (!backgroundProcess) return;
|
|
2497
|
-
backgroundProcess.code = backgroundProcess.code ?? 2;
|
|
2498
|
-
});
|
|
2499
|
-
return execHandle;
|
|
2500
|
-
}
|
|
2501
|
-
async exec(command, abortSignal, timeout, options) {
|
|
2502
|
-
const DEFAULT_TIMEOUT = 12e4;
|
|
2503
|
-
const commandTimeout = timeout ?? DEFAULT_TIMEOUT;
|
|
2504
|
-
this.abortController = new AbortController();
|
|
2505
|
-
let wasAborted = false;
|
|
2506
|
-
const onAbort = () => {
|
|
2507
|
-
wasAborted = true;
|
|
2508
|
-
try {
|
|
2509
|
-
this.abortController?.abort();
|
|
2510
|
-
} catch {
|
|
2511
|
-
}
|
|
2512
|
-
try {
|
|
2513
|
-
this.currentProcess?.kill();
|
|
2514
|
-
} catch {
|
|
2515
|
-
}
|
|
2516
|
-
};
|
|
2517
|
-
if (abortSignal) {
|
|
2518
|
-
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
2519
|
-
}
|
|
2520
|
-
const sandbox = options?.sandbox;
|
|
2521
|
-
const shouldAttemptSandbox = sandbox?.enabled === true;
|
|
2522
|
-
const executionCwd = shouldAttemptSandbox && sandbox?.chdir ? sandbox.chdir : this.cwd;
|
|
2523
|
-
const runOnce = async (cmd, cwdOverride) => {
|
|
2524
|
-
this.currentProcess = spawnWithExited({
|
|
2525
|
-
cmd,
|
|
2526
|
-
cwd: cwdOverride ?? executionCwd
|
|
2527
|
-
});
|
|
2528
|
-
const stdoutCollector = this.createCancellableTextCollector(
|
|
2529
|
-
this.currentProcess.stdout,
|
|
2530
|
-
{ onChunk: options?.onStdoutChunk }
|
|
2531
|
-
);
|
|
2532
|
-
const stderrCollector = this.createCancellableTextCollector(
|
|
2533
|
-
this.currentProcess.stderr,
|
|
2534
|
-
{ onChunk: options?.onStderrChunk }
|
|
2535
|
-
);
|
|
2536
|
-
let timeoutHandle = null;
|
|
2537
|
-
const timeoutPromise = new Promise((resolve3) => {
|
|
2538
|
-
timeoutHandle = setTimeout(() => resolve3("timeout"), commandTimeout);
|
|
2539
|
-
});
|
|
2540
|
-
const result = await Promise.race([
|
|
2541
|
-
this.currentProcess.exited.then(() => "completed"),
|
|
2542
|
-
timeoutPromise
|
|
2543
|
-
]);
|
|
2544
|
-
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
2545
|
-
if (result === "timeout") {
|
|
2546
|
-
try {
|
|
2547
|
-
this.currentProcess.kill();
|
|
2548
|
-
} catch {
|
|
2549
|
-
}
|
|
2550
|
-
try {
|
|
2551
|
-
this.abortController.abort();
|
|
2552
|
-
} catch {
|
|
2553
|
-
}
|
|
2554
|
-
try {
|
|
2555
|
-
await this.currentProcess.exited;
|
|
2556
|
-
} catch {
|
|
2557
|
-
}
|
|
2558
|
-
await Promise.race([
|
|
2559
|
-
Promise.allSettled([stdoutCollector.done, stderrCollector.done]),
|
|
2560
|
-
new Promise((resolve3) => setTimeout(resolve3, 250))
|
|
2561
|
-
]);
|
|
2562
|
-
await Promise.allSettled([
|
|
2563
|
-
stdoutCollector.cancel(),
|
|
2564
|
-
stderrCollector.cancel()
|
|
2565
|
-
]);
|
|
2566
|
-
return {
|
|
2567
|
-
stdout: "",
|
|
2568
|
-
stderr: "Command timed out",
|
|
2569
|
-
code: 143,
|
|
2570
|
-
interrupted: true
|
|
2571
|
-
};
|
|
2572
|
-
}
|
|
2573
|
-
await Promise.race([
|
|
2574
|
-
Promise.allSettled([stdoutCollector.done, stderrCollector.done]),
|
|
2575
|
-
new Promise((resolve3) => setTimeout(resolve3, 250))
|
|
2576
|
-
]);
|
|
2577
|
-
await Promise.allSettled([
|
|
2578
|
-
stdoutCollector.cancel(),
|
|
2579
|
-
stderrCollector.cancel()
|
|
2580
|
-
]);
|
|
2581
|
-
const stdout = stdoutCollector.getText();
|
|
2582
|
-
const stderr = stderrCollector.getText();
|
|
2583
|
-
const interrupted = wasAborted || abortSignal?.aborted === true || this.abortController?.signal.aborted === true;
|
|
2584
|
-
const exitCode = this.currentProcess.exitCode ?? (interrupted ? 143 : 0);
|
|
2585
|
-
return {
|
|
2586
|
-
stdout,
|
|
2587
|
-
stderr,
|
|
2588
|
-
code: exitCode,
|
|
2589
|
-
interrupted
|
|
2590
|
-
};
|
|
2591
|
-
};
|
|
2592
|
-
try {
|
|
2593
|
-
if (shouldAttemptSandbox) {
|
|
2594
|
-
const sandboxCmd = this.buildSandboxCmd(command, sandbox);
|
|
2595
|
-
if (!sandboxCmd) {
|
|
2596
|
-
if (sandbox?.require) {
|
|
2597
|
-
return {
|
|
2598
|
-
stdout: "",
|
|
2599
|
-
stderr: "System sandbox is required but unavailable (missing bubblewrap or unsupported platform).",
|
|
2600
|
-
code: 2,
|
|
2601
|
-
interrupted: false
|
|
2602
|
-
};
|
|
2603
|
-
}
|
|
2604
|
-
const fallback = await runOnce(this.getShellCmd(command));
|
|
2605
|
-
return {
|
|
2606
|
-
...fallback,
|
|
2607
|
-
stderr: `[sandbox] unavailable, ran without isolation.
|
|
2608
|
-
${fallback.stderr}`.trim()
|
|
2609
|
-
};
|
|
2610
|
-
}
|
|
2611
|
-
const sandboxed = await runOnce(sandboxCmd.cmd);
|
|
2612
|
-
sandboxed.stderr = maybeAnnotateMacosSandboxStderr(
|
|
2613
|
-
sandboxed.stderr,
|
|
2614
|
-
sandbox
|
|
2615
|
-
);
|
|
2616
|
-
if (!sandboxed.interrupted && sandboxed.code !== 0 && this.isSandboxInitFailure(sandboxed.stderr) && !sandbox?.require) {
|
|
2617
|
-
const fallback = await runOnce(this.getShellCmd(command));
|
|
2618
|
-
return {
|
|
2619
|
-
...fallback,
|
|
2620
|
-
stderr: `[sandbox] failed to start, ran without isolation.
|
|
2621
|
-
${fallback.stderr}`.trim()
|
|
2622
|
-
};
|
|
2623
|
-
}
|
|
2624
|
-
return sandboxed;
|
|
2625
|
-
}
|
|
2626
|
-
return await runOnce(this.getShellCmd(command));
|
|
2627
|
-
} catch (error) {
|
|
2628
|
-
if (this.abortController.signal.aborted) {
|
|
2629
|
-
this.currentProcess?.kill();
|
|
2630
|
-
return {
|
|
2631
|
-
stdout: "",
|
|
2632
|
-
stderr: "Command was interrupted",
|
|
2633
|
-
code: 143,
|
|
2634
|
-
interrupted: true
|
|
2635
|
-
};
|
|
2636
|
-
}
|
|
2637
|
-
const errorStr = error instanceof Error ? error.message : String(error);
|
|
2638
|
-
logError(`Shell execution error: ${errorStr}`);
|
|
2639
|
-
return {
|
|
2640
|
-
stdout: "",
|
|
2641
|
-
stderr: errorStr,
|
|
2642
|
-
code: 2,
|
|
2643
|
-
interrupted: false
|
|
2644
|
-
};
|
|
2645
|
-
} finally {
|
|
2646
|
-
if (abortSignal) {
|
|
2647
|
-
abortSignal.removeEventListener("abort", onAbort);
|
|
2648
|
-
}
|
|
2649
|
-
this.currentProcess = null;
|
|
2650
|
-
this.abortController = null;
|
|
2651
|
-
}
|
|
2652
|
-
}
|
|
2653
|
-
execInBackground(command, timeout, options) {
|
|
2654
|
-
const DEFAULT_TIMEOUT = 12e4;
|
|
2655
|
-
const commandTimeout = timeout ?? DEFAULT_TIMEOUT;
|
|
2656
|
-
const abortController = new AbortController();
|
|
2657
|
-
const sandbox = options?.sandbox;
|
|
2658
|
-
const sandboxCmd = sandbox?.enabled === true ? this.buildSandboxCmd(command, sandbox) : null;
|
|
2659
|
-
const executionCwd = sandbox?.enabled === true && sandbox?.chdir ? sandbox.chdir : this.cwd;
|
|
2660
|
-
if (sandbox?.enabled === true && sandbox?.require && !sandboxCmd) {
|
|
2661
|
-
throw new Error(
|
|
2662
|
-
"System sandbox is required but unavailable (missing bubblewrap or unsupported platform)."
|
|
2663
|
-
);
|
|
2664
|
-
}
|
|
2665
|
-
const cmdToRun = sandboxCmd ? sandboxCmd.cmd : this.getShellCmd(command);
|
|
2666
|
-
const bashId = _BunShell.makeBackgroundTaskId();
|
|
2667
|
-
const outputFile = touchTaskOutputFile(bashId);
|
|
2668
|
-
const process2 = spawnWithExited({ cmd: cmdToRun, cwd: executionCwd });
|
|
2669
|
-
const timeoutHandle = setTimeout(() => {
|
|
2670
|
-
abortController.abort();
|
|
2671
|
-
backgroundProcess.timedOut = true;
|
|
2672
|
-
process2.kill();
|
|
2673
|
-
}, commandTimeout);
|
|
2674
|
-
const backgroundProcess = {
|
|
2675
|
-
id: bashId,
|
|
2676
|
-
command,
|
|
2677
|
-
stdout: "",
|
|
2678
|
-
stderr: "",
|
|
2679
|
-
stdoutCursor: 0,
|
|
2680
|
-
stderrCursor: 0,
|
|
2681
|
-
stdoutLineCount: 0,
|
|
2682
|
-
stderrLineCount: 0,
|
|
2683
|
-
lastReportedStdoutLines: 0,
|
|
2684
|
-
lastReportedStderrLines: 0,
|
|
2685
|
-
code: null,
|
|
2686
|
-
interrupted: false,
|
|
2687
|
-
killed: false,
|
|
2688
|
-
timedOut: false,
|
|
2689
|
-
completionStatusSentInAttachment: false,
|
|
2690
|
-
notified: false,
|
|
2691
|
-
startedAt: Date.now(),
|
|
2692
|
-
timeoutAt: Date.now() + commandTimeout,
|
|
2693
|
-
process: process2,
|
|
2694
|
-
abortController,
|
|
2695
|
-
timeoutHandle,
|
|
2696
|
-
cwd: executionCwd,
|
|
2697
|
-
outputFile
|
|
2698
|
-
};
|
|
2699
|
-
const countNonEmptyLines = (chunk) => chunk.split("\n").filter((line) => line.length > 0).length;
|
|
2700
|
-
this.startStreamReader(process2.stdout, (chunk) => {
|
|
2701
|
-
backgroundProcess.stdout += chunk;
|
|
2702
|
-
appendTaskOutput(bashId, chunk);
|
|
2703
|
-
backgroundProcess.stdoutLineCount += countNonEmptyLines(chunk);
|
|
2704
|
-
});
|
|
2705
|
-
this.startStreamReader(process2.stderr, (chunk) => {
|
|
2706
|
-
backgroundProcess.stderr += chunk;
|
|
2707
|
-
appendTaskOutput(bashId, chunk);
|
|
2708
|
-
backgroundProcess.stderrLineCount += countNonEmptyLines(chunk);
|
|
2709
|
-
});
|
|
2710
|
-
process2.exited.then(() => {
|
|
2711
|
-
backgroundProcess.code = process2.exitCode ?? 0;
|
|
2712
|
-
backgroundProcess.interrupted = backgroundProcess.interrupted || abortController.signal.aborted;
|
|
2713
|
-
if (sandbox?.enabled === true) {
|
|
2714
|
-
backgroundProcess.stderr = maybeAnnotateMacosSandboxStderr(
|
|
2715
|
-
backgroundProcess.stderr,
|
|
2716
|
-
sandbox
|
|
2717
|
-
);
|
|
2718
|
-
}
|
|
2719
|
-
if (backgroundProcess.timeoutHandle) {
|
|
2720
|
-
clearTimeout(backgroundProcess.timeoutHandle);
|
|
2721
|
-
backgroundProcess.timeoutHandle = null;
|
|
2722
|
-
}
|
|
2723
|
-
});
|
|
2724
|
-
this.backgroundProcesses.set(bashId, backgroundProcess);
|
|
2725
|
-
return { bashId };
|
|
2726
|
-
}
|
|
2727
|
-
getBackgroundOutput(shellId) {
|
|
2728
|
-
const proc = this.backgroundProcesses.get(shellId);
|
|
2729
|
-
if (!proc) return null;
|
|
2730
|
-
const running = proc.code === null && !proc.interrupted;
|
|
2731
|
-
return {
|
|
2732
|
-
stdout: proc.stdout,
|
|
2733
|
-
stderr: proc.stderr,
|
|
2734
|
-
code: proc.code,
|
|
2735
|
-
interrupted: proc.interrupted,
|
|
2736
|
-
killed: proc.killed,
|
|
2737
|
-
timedOut: proc.timedOut,
|
|
2738
|
-
running,
|
|
2739
|
-
command: proc.command,
|
|
2740
|
-
cwd: proc.cwd,
|
|
2741
|
-
startedAt: proc.startedAt,
|
|
2742
|
-
timeoutAt: proc.timeoutAt,
|
|
2743
|
-
outputFile: proc.outputFile
|
|
2744
|
-
};
|
|
2745
|
-
}
|
|
2746
|
-
readBackgroundOutput(bashId, options) {
|
|
2747
|
-
const proc = this.backgroundProcesses.get(bashId);
|
|
2748
|
-
if (!proc) return null;
|
|
2749
|
-
const stdoutDelta = proc.stdout.slice(proc.stdoutCursor);
|
|
2750
|
-
const stderrDelta = proc.stderr.slice(proc.stderrCursor);
|
|
2751
|
-
proc.stdoutCursor = proc.stdout.length;
|
|
2752
|
-
proc.stderrCursor = proc.stderr.length;
|
|
2753
|
-
const stdoutLines = stdoutDelta === "" ? 0 : stdoutDelta.split("\n").length;
|
|
2754
|
-
const stderrLines = stderrDelta === "" ? 0 : stderrDelta.split("\n").length;
|
|
2755
|
-
let stdoutToReturn = stdoutDelta;
|
|
2756
|
-
let stderrToReturn = stderrDelta;
|
|
2757
|
-
const filter = options?.filter?.trim();
|
|
2758
|
-
if (filter) {
|
|
2759
|
-
const regex = new RegExp(filter, "i");
|
|
2760
|
-
stdoutToReturn = stdoutDelta.split("\n").filter((line) => regex.test(line)).join("\n");
|
|
2761
|
-
stderrToReturn = stderrDelta.split("\n").filter((line) => regex.test(line)).join("\n");
|
|
2762
|
-
}
|
|
2763
|
-
const status = proc.killed ? "killed" : proc.code === null ? "running" : proc.code === 0 ? "completed" : "failed";
|
|
2764
|
-
return {
|
|
2765
|
-
shellId: bashId,
|
|
2766
|
-
command: proc.command,
|
|
2767
|
-
cwd: proc.cwd,
|
|
2768
|
-
startedAt: proc.startedAt,
|
|
2769
|
-
timeoutAt: proc.timeoutAt,
|
|
2770
|
-
status,
|
|
2771
|
-
exitCode: proc.code,
|
|
2772
|
-
stdout: stdoutToReturn,
|
|
2773
|
-
stderr: stderrToReturn,
|
|
2774
|
-
stdoutLines,
|
|
2775
|
-
stderrLines,
|
|
2776
|
-
...filter ? { filterPattern: filter } : {}
|
|
2777
|
-
};
|
|
2778
|
-
}
|
|
2779
|
-
killBackgroundShell(shellId) {
|
|
2780
|
-
const proc = this.backgroundProcesses.get(shellId);
|
|
2781
|
-
if (!proc) return false;
|
|
2782
|
-
try {
|
|
2783
|
-
proc.interrupted = true;
|
|
2784
|
-
proc.killed = true;
|
|
2785
|
-
proc.abortController.abort();
|
|
2786
|
-
proc.process.kill();
|
|
2787
|
-
if (proc.timeoutHandle) {
|
|
2788
|
-
clearTimeout(proc.timeoutHandle);
|
|
2789
|
-
proc.timeoutHandle = null;
|
|
2790
|
-
}
|
|
2791
|
-
return true;
|
|
2792
|
-
} catch {
|
|
2793
|
-
return false;
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
listBackgroundShells() {
|
|
2797
|
-
return Array.from(this.backgroundProcesses.values());
|
|
2798
|
-
}
|
|
2799
|
-
pwd() {
|
|
2800
|
-
return this.cwd;
|
|
2801
|
-
}
|
|
2802
|
-
async setCwd(cwd2) {
|
|
2803
|
-
const resolved = isAbsolute2(cwd2) ? cwd2 : resolve2(this.cwd, cwd2);
|
|
2804
|
-
if (!existsSync4(resolved)) {
|
|
2805
|
-
throw new Error(`Path "${resolved}" does not exist`);
|
|
2806
|
-
}
|
|
2807
|
-
this.cwd = resolved;
|
|
2808
|
-
}
|
|
2809
|
-
killChildren() {
|
|
2810
|
-
this.abortController?.abort();
|
|
2811
|
-
this.currentProcess?.kill();
|
|
2812
|
-
for (const bg of Array.from(this.backgroundProcesses.keys())) {
|
|
2813
|
-
this.killBackgroundShell(bg);
|
|
2814
|
-
}
|
|
2815
|
-
}
|
|
2816
|
-
close() {
|
|
2817
|
-
this.isAlive = false;
|
|
2818
|
-
this.killChildren();
|
|
2819
|
-
}
|
|
2820
|
-
flushBashNotifications() {
|
|
2821
|
-
const processes = Array.from(this.backgroundProcesses.values());
|
|
2822
|
-
const statusFor = (proc) => proc.killed ? "killed" : proc.code === null ? "running" : proc.code === 0 ? "completed" : "failed";
|
|
2823
|
-
const notifications = [];
|
|
2824
|
-
for (const proc of processes) {
|
|
2825
|
-
if (proc.notified) continue;
|
|
2826
|
-
const status = statusFor(proc);
|
|
2827
|
-
if (status === "running") continue;
|
|
2828
|
-
notifications.push({
|
|
2829
|
-
type: "bash_notification",
|
|
2830
|
-
taskId: proc.id,
|
|
2831
|
-
description: proc.command,
|
|
2832
|
-
outputFile: proc.outputFile || getTaskOutputFilePath(proc.id),
|
|
2833
|
-
status,
|
|
2834
|
-
...proc.code !== null ? { exitCode: proc.code } : {}
|
|
2835
|
-
});
|
|
2836
|
-
proc.notified = true;
|
|
2837
|
-
}
|
|
2838
|
-
return notifications;
|
|
2839
|
-
}
|
|
2840
|
-
flushBackgroundShellStatusAttachments() {
|
|
2841
|
-
const processes = Array.from(this.backgroundProcesses.values());
|
|
2842
|
-
const statusFor = (proc) => proc.killed ? "killed" : proc.code === null ? "running" : proc.code === 0 ? "completed" : "failed";
|
|
2843
|
-
const progressAttachments = [];
|
|
2844
|
-
for (const proc of processes) {
|
|
2845
|
-
if (statusFor(proc) !== "running") continue;
|
|
2846
|
-
const stdoutDelta = proc.stdoutLineCount - proc.lastReportedStdoutLines;
|
|
2847
|
-
const stderrDelta = proc.stderrLineCount - proc.lastReportedStderrLines;
|
|
2848
|
-
if (stdoutDelta === 0 && stderrDelta === 0) continue;
|
|
2849
|
-
proc.lastReportedStdoutLines = proc.stdoutLineCount;
|
|
2850
|
-
proc.lastReportedStderrLines = proc.stderrLineCount;
|
|
2851
|
-
progressAttachments.push({
|
|
2852
|
-
type: "task_progress",
|
|
2853
|
-
taskId: proc.id,
|
|
2854
|
-
stdoutLineDelta: stdoutDelta,
|
|
2855
|
-
stderrLineDelta: stderrDelta,
|
|
2856
|
-
outputFile: proc.outputFile || getTaskOutputFilePath(proc.id)
|
|
2857
|
-
});
|
|
2858
|
-
}
|
|
2859
|
-
return progressAttachments;
|
|
2860
|
-
}
|
|
2861
|
-
};
|
|
2862
|
-
|
|
2863
|
-
// src/utils/state/index.ts
|
|
2864
|
-
var STATE = {
|
|
2865
|
-
originalCwd: cwd()
|
|
2866
|
-
};
|
|
2867
|
-
async function setCwd(cwd2) {
|
|
2868
|
-
await BunShell.getInstance().setCwd(cwd2);
|
|
2869
|
-
}
|
|
2870
|
-
function setOriginalCwd(cwd2) {
|
|
2871
|
-
STATE.originalCwd = cwd2;
|
|
2872
|
-
}
|
|
2873
|
-
function getOriginalCwd() {
|
|
2874
|
-
return STATE.originalCwd;
|
|
2875
|
-
}
|
|
2876
|
-
function getCwd() {
|
|
2877
|
-
return BunShell.getInstance().pwd();
|
|
2878
|
-
}
|
|
2879
|
-
|
|
2880
|
-
export {
|
|
2881
|
-
initSentry,
|
|
2882
|
-
captureException,
|
|
2883
|
-
PRODUCT_NAME,
|
|
2884
|
-
PROJECT_FILE,
|
|
2885
|
-
PRODUCT_COMMAND,
|
|
2886
|
-
CONFIG_BASE_DIR,
|
|
2887
|
-
GITHUB_ISSUES_REPO_URL,
|
|
2888
|
-
ASCII_LOGO,
|
|
2889
|
-
getTaskOutputFilePath,
|
|
2890
|
-
readTaskOutput,
|
|
2891
|
-
renderBackgroundShellStatusAttachment,
|
|
2892
|
-
renderBashNotification,
|
|
2893
|
-
BunShell,
|
|
2894
|
-
setCwd,
|
|
2895
|
-
setOriginalCwd,
|
|
2896
|
-
getOriginalCwd,
|
|
2897
|
-
getCwd,
|
|
2898
|
-
execFileNoThrow,
|
|
2899
|
-
getKodeBaseDir,
|
|
2900
|
-
getGlobalConfigFilePath,
|
|
2901
|
-
getMemoryDir,
|
|
2902
|
-
KODE_BASE_DIR,
|
|
2903
|
-
GLOBAL_CONFIG_FILE,
|
|
2904
|
-
MEMORY_DIR,
|
|
2905
|
-
env,
|
|
2906
|
-
PLAN_SLUG_ADJECTIVES,
|
|
2907
|
-
PLAN_SLUG_VERBS,
|
|
2908
|
-
PLAN_SLUG_NOUNS,
|
|
2909
|
-
getPlanConversationKey,
|
|
2910
|
-
setActivePlanConversationKey,
|
|
2911
|
-
getPlanModeSystemPromptAdditions,
|
|
2912
|
-
enterPlanMode,
|
|
2913
|
-
enterPlanModeForConversationKey,
|
|
2914
|
-
exitPlanModeForConversationKey,
|
|
2915
|
-
hydratePlanSlugFromMessages,
|
|
2916
|
-
getPlanFilePath,
|
|
2917
|
-
isMainPlanFilePathForActiveConversation,
|
|
2918
|
-
readPlanFile,
|
|
2919
|
-
SESSION_ID,
|
|
2920
|
-
CACHE_PATHS,
|
|
2921
|
-
dateToFilename,
|
|
2922
|
-
getMessagesPath,
|
|
2923
|
-
logError,
|
|
2924
|
-
overwriteLog,
|
|
2925
|
-
loadLogList,
|
|
2926
|
-
parseLogFilename,
|
|
2927
|
-
getNextAvailableLogForkNumber,
|
|
2928
|
-
getNextAvailableLogSidechainNumber,
|
|
2929
|
-
formatDate,
|
|
2930
|
-
logMCPError
|
|
2931
|
-
};
|