nolo-cli 0.213.0 → 0.222.0-alpha.2
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/README.md +3 -2
- package/{_executeModel-CUJLCFWR.js → _executeModel-4GGQQHOB.js} +111 -82
- package/{accountResolver-4LKIHEKL.js → accountResolver-EK2S4PWF.js} +6 -6
- package/{action-DF5UYSJF.js → action-CK64LS6S.js} +12 -11
- package/{addContentAction-WERAONNY.js → addContentAction-GDHDOF4U.js} +18 -17
- package/{addDialogAgentAction-7VI7YRML.js → addDialogAgentAction-CAKRU3ZT.js} +21 -20
- package/{agentDeleteCommand-XJORXPGU.js → agentDeleteCommand-BPV2XZL7.js} +128 -119
- package/{agentEmailCommands-XTYYFR6Z.js → agentEmailCommands-EJOS75YL.js} +132 -124
- package/{agentFavoriteCommands-EDK743YA.js → agentFavoriteCommands-2LKGKSUD.js} +7 -8
- package/{agentGrantCommands-RQWK2TEV.js → agentGrantCommands-QQV4N4JW.js} +5 -5
- package/{agentListCommands-OBLRBLHS.js → agentListCommands-HIZODBF3.js} +155 -92
- package/{agentMachineCommands-5FMT3OT5.js → agentMachineCommands-ZMQ2CY7Y.js} +62 -54
- package/{agentProviderCommands-Q5O33MED.js → agentProviderCommands-WKJOAWBP.js} +5 -5
- package/{agentPullCommand-6EM3URVK.js → agentPullCommand-XN6ZPBUW.js} +7 -7
- package/agentRecordCommands-OMXVDLDX.js +176 -0
- package/agentRunCommand-CB34YWMV.js +206 -0
- package/{agentRunControl-TAMHJQSR.js → agentRunControl-JNONH3RP.js} +30 -15
- package/{agentRuntimeLocal-SOO2OPJG.js → agentRuntimeLocal-QZPFWMLG.js} +52 -45
- package/{agentSlice-CHR6KOZN.js → agentSlice-RD2CDU7T.js} +20 -19
- package/{appDeleteCommands-GUP6P5YE.js → appDeleteCommands-QCCFDIEQ.js} +61 -53
- package/{appDeployCommands-MH2FX4O5.js → appDeployCommands-V2T7TNMQ.js} +61 -53
- package/{appDeployStatusCommands-SUHN3HPJ.js → appDeployStatusCommands-6PGH7ZCG.js} +61 -53
- package/{appGetCommands-YWDEX6Z4.js → appGetCommands-3L7WWJA6.js} +61 -53
- package/{appListCommands-ZQVMLPAY.js → appListCommands-ENJCK4PO.js} +61 -53
- package/{authCommand-PWX2ZNUP.js → authCommand-6V47SYGK.js} +29 -28
- package/{authCommands-HV3EAU3V.js → authCommands-GAJ3NIXO.js} +14 -13
- package/{builtinSkillRegistry-2QETTQPM.js → builtinSkillRegistry-2ECA42FC.js} +11 -13
- package/{chromeCommands-REEAH4SX.js → chromeCommands-G5UDKVSV.js} +3 -3
- package/{chromeOpsCommands-DIVM2K3T.js → chromeOpsCommands-YKX2QX3A.js} +20 -10
- package/{chunk-CRHOO2ZR.js → chunk-27PCUMJI.js} +2 -2
- package/chunk-2CI3ZFWD.js +97 -0
- package/{chunk-NSAPDIN2.js → chunk-2GJKRKI6.js} +541 -31
- package/{chunk-SM3NSZJV.js → chunk-2UCBGYO4.js} +20 -1
- package/{chunk-PYRUW7XN.js → chunk-2VUZSVAS.js} +136 -54
- package/{chunk-YB3YZK56.js → chunk-2WZXXAQD.js} +1 -67
- package/chunk-2YGBI2XB.js +30 -0
- package/chunk-2ZKFCIJJ.js +13 -0
- package/{chunk-QG4AOSON.js → chunk-34J5K2YA.js} +13 -32
- package/{chunk-LOEO7LRC.js → chunk-3IK6ILVW.js} +4 -1
- package/{chunk-CTPXME7U.js → chunk-3LMUPOHG.js} +29 -6
- package/chunk-44X52WOJ.js +1621 -0
- package/{chunk-6VLJ6YA7.js → chunk-4DESLZTK.js} +9 -9
- package/{chunk-MYOH447Z.js → chunk-4JVNURX4.js} +1 -1
- package/chunk-5CHGAKRT.js +364 -0
- package/{chunk-YDH3FDFQ.js → chunk-5FUN7EG4.js} +1 -1
- package/{chunk-INUFILG6.js → chunk-5RKUPJYL.js} +1 -1
- package/{chunk-ZC3CMUKU.js → chunk-6OVNSQHN.js} +84 -2
- package/{chunk-MOIJOHA5.js → chunk-6WU5572L.js} +36 -25
- package/{chunk-IXNGOHV5.js → chunk-7EEZJ6BS.js} +11 -152
- package/{chunk-Y6ORVLSS.js → chunk-7ET2U67U.js} +1 -1
- package/{chunk-G7MLNNEX.js → chunk-7JLY4WYF.js} +5 -5
- package/{chunk-P5L7CXOC.js → chunk-7Z6EW7AH.js} +3 -2
- package/{chunk-NJLL224W.js → chunk-AD5EWDFD.js} +2 -2
- package/{chunk-J2NHJ7WX.js → chunk-AIHYNKGV.js} +4 -4
- package/{chunk-HPFCI4SK.js → chunk-AK5O76CC.js} +3 -3
- package/{chunk-Y63ZSOR6.js → chunk-AL3TYDIF.js} +1 -1
- package/{chunk-ALQ3657A.js → chunk-AMEOV5VZ.js} +32 -12
- package/chunk-AN74ON4G.js +675 -0
- package/{chunk-HRMJUN5J.js → chunk-AQZ6BMRK.js} +1 -1
- package/{chunk-XHQC4PXX.js → chunk-B4GOW4MT.js} +424 -194
- package/{chunk-4KB6WQUL.js → chunk-BGP2EDFG.js} +1 -1
- package/{chunk-NBTY7YJF.js → chunk-BR3GT6MR.js} +1 -0
- package/{chunk-7RFNTILS.js → chunk-BUDVRYES.js} +2 -2
- package/{chunk-SVYO6AO7.js → chunk-BV3FLP2L.js} +41 -1
- package/{chunk-RZOV7OMV.js → chunk-C4VAR65S.js} +83 -141
- package/{chunk-COFEN36Z.js → chunk-C4WTX5TU.js} +2 -2
- package/{chunk-ZL5RAEEB.js → chunk-CIRB724Q.js} +1 -1
- package/{chunk-F6UUQOG6.js → chunk-CKT6QUE2.js} +4 -4
- package/{chunk-X7SDOJUM.js → chunk-CMZ3Z5PT.js} +14 -14
- package/{secretCommands-LXDWOLZ6.js → chunk-D726I5AZ.js} +191 -16
- package/{chunk-TAKB25RM.js → chunk-DNKTQ3IN.js} +4 -4
- package/chunk-DVQH4BTR.js +1137 -0
- package/{chunk-WYDI6TGM.js → chunk-DWX2HEVC.js} +91 -132
- package/{chunk-5MQRBSMW.js → chunk-EIAI3PPH.js} +111 -113
- package/chunk-EUCFKKDM.js +247 -0
- package/chunk-EWQ3HGNZ.js +90 -0
- package/{chunk-RPQXPZZF.js → chunk-F3GRJO4Z.js} +908 -13
- package/{chunk-YTF4WH7J.js → chunk-FIYSMXHY.js} +1 -1
- package/{chunk-75XIDFBW.js → chunk-FJ23FZXF.js} +72 -28
- package/{chunk-INN4LTAJ.js → chunk-FJK526XH.js} +2 -2
- package/chunk-FS2XP5D7.js +142 -0
- package/{chunk-FUGMREBO.js → chunk-FYF2TONJ.js} +5 -5
- package/{chunk-PCLE46CE.js → chunk-GBWGPTA7.js} +2 -1
- package/{chunk-TX5EYMGT.js → chunk-GYVCJABP.js} +30 -254
- package/{chunk-3UKL3HPD.js → chunk-HOCHUZQ7.js} +8 -78
- package/{chunk-EHSZD5OI.js → chunk-HXER7YJF.js} +4 -4
- package/chunk-HYIETXA6.js +99 -0
- package/{chunk-H2TJUNCH.js → chunk-I4EADJ4P.js} +6 -6
- package/{chunk-TCZHTTUU.js → chunk-I7WBYGBP.js} +8 -8
- package/{chunk-6DWMYIUY.js → chunk-IILMY4W4.js} +14 -9
- package/chunk-JA3ICVJY.js +271 -0
- package/{chunk-ZRSNONOB.js → chunk-JWXITTQB.js} +8 -3
- package/{chunk-H4UOTUOX.js → chunk-KEN3N2TN.js} +148 -18
- package/{chunk-LEC5ALIN.js → chunk-KEPOVMF4.js} +1 -1
- package/{chunk-UHJGXRJ4.js → chunk-KQSYAIZR.js} +3 -3
- package/{chunk-4VJAC32I.js → chunk-L5I543VB.js} +3 -2
- package/chunk-LKA64WH4.js +227 -0
- package/{chunk-QHPRUL4O.js → chunk-LVL6GFCM.js} +4 -4
- package/{chunk-H5HF7TJA.js → chunk-MAIITKBT.js} +2 -2
- package/chunk-MBG66ZBH.js +226 -0
- package/{chunk-YUA6OAH5.js → chunk-MDLS23JK.js} +2 -2
- package/{chunk-VL5KOY2C.js → chunk-MK2Q7ZJD.js} +67 -5
- package/{chunk-MDB67IWP.js → chunk-MS4NZNKI.js} +10 -10
- package/{chunk-VO4WSAVP.js → chunk-MYHNBEXD.js} +3 -3
- package/{chunk-ZXOUUDCG.js → chunk-MZLE5HQ3.js} +3654 -231
- package/{chunk-AZMYUSVF.js → chunk-N5Z2V73W.js} +1 -1
- package/{chunk-V5Y3R6BT.js → chunk-NIZ2BXFD.js} +213 -210
- package/{chunk-KFLT5KAD.js → chunk-NWP2OYOX.js} +20 -20
- package/{chunk-G2BQWAVT.js → chunk-O6J3OTOP.js} +4 -4
- package/{chunk-VNYYOX3V.js → chunk-OB6DVWPF.js} +141 -48
- package/{chunk-YWSEPJ7C.js → chunk-OBWT45ZU.js} +3 -3
- package/{chunk-ZNWI6OVT.js → chunk-ODJ7BVSI.js} +80 -11
- package/{chunk-XJWWBO34.js → chunk-OJKUU3LP.js} +5 -7
- package/{chunk-HUBHAQK2.js → chunk-ON37YXGX.js} +29 -29
- package/{chunk-UYD5HQ6T.js → chunk-P5ZJRTCH.js} +5429 -1752
- package/{chunk-6XIE5ZGI.js → chunk-PDCV7P5W.js} +1 -1
- package/{chunk-WRYQ35LQ.js → chunk-PJCIP64Z.js} +859 -57
- package/{chunk-7QTZCMKL.js → chunk-PJVKMGPZ.js} +1089 -1639
- package/{chunk-A7TFUNZO.js → chunk-PPJYZRSQ.js} +6 -2
- package/chunk-QHEN7NZ7.js +46 -0
- package/{chunk-OQPKUBPB.js → chunk-QNWG52I4.js} +19 -7
- package/{chunk-YGILMZ7N.js → chunk-QVBXJNZ2.js} +1 -1
- package/{chunk-7BT37FK3.js → chunk-RDH5CQ4T.js} +648 -131
- package/{chunk-C6KNNXWU.js → chunk-RGQ4UUWZ.js} +25 -2
- package/{chunk-OWYYDMGJ.js → chunk-S2NTVGA2.js} +4 -2
- package/{chunk-KC4XDTT3.js → chunk-SOF4OWDM.js} +6 -4
- package/{chunk-RLBNLZVC.js → chunk-SQYIK6HO.js} +1 -1
- package/{chunk-YJAFKXMU.js → chunk-SVT62ULE.js} +50 -48
- package/{chunk-KIM6CLW5.js → chunk-SY3C4SQ7.js} +42 -15
- package/{chunk-JY5NGFFH.js → chunk-SYTHYBMI.js} +5 -5
- package/{chunk-WMTBPBMP.js → chunk-T6DXNI6Z.js} +52 -50
- package/chunk-TLE77UJ5.js +230 -0
- package/{chunk-4VNS5WPM.js → chunk-U67V476Y.js} +1 -8
- package/{chunk-F7CI2ZC5.js → chunk-UAIHKQIA.js} +2 -1
- package/{chunk-R5O4QAWG.js → chunk-UB3D4TRQ.js} +11 -77
- package/{chunk-WPORQFYN.js → chunk-UVLYNWIE.js} +2 -2
- package/{chunk-NOKUNJON.js → chunk-UYOICCYG.js} +29 -19
- package/{chunk-4I7ERB7F.js → chunk-VREDDN25.js} +1 -1
- package/{chunk-O2TZF4AI.js → chunk-WAE3GFCJ.js} +3 -3
- package/{chunk-H7PPIYWP.js → chunk-WI67URFP.js} +20 -20
- package/{chunk-7OCO4TDT.js → chunk-WJVYAO6P.js} +1 -1
- package/{chunk-T43B7LB2.js → chunk-WKGQSYTB.js} +1 -1
- package/{chunk-BBJ22CLB.js → chunk-WUUH4LWZ.js} +60 -30
- package/{chunk-4T2WNOY7.js → chunk-X7UF53VA.js} +33 -22
- package/{chunk-TY3TIUJK.js → chunk-XI2BWJM5.js} +65 -0
- package/{chunk-LLRPJECG.js → chunk-XWVCYUUU.js} +16 -159
- package/{chunk-J5JTMQIA.js → chunk-YFLVRVYK.js} +1 -1
- package/{chunk-EYLGAEB4.js → chunk-YGMBIXCF.js} +132 -0
- package/chunk-YL3EFYL3.js +199 -0
- package/{chunk-MMA3LZ3W.js → chunk-YNIYE47Z.js} +1 -1
- package/{chunk-W4S457LU.js → chunk-YU4ZPWVF.js} +41 -5
- package/{chunk-7Y4YTDQF.js → chunk-YWWDC3O7.js} +281 -159
- package/chunk-YZMNK53S.js +68 -0
- package/{chunk-RSHTSUEG.js → chunk-Z2PITYZN.js} +2060 -602
- package/{chunk-FY7F4Q6X.js → chunk-Z4PCXPUE.js} +2 -2
- package/{cliAgentConfigHelpers-WJBZQTLW.js → cliAgentConfigHelpers-TKYL43MT.js} +15 -16
- package/{cliAuthorityBrokerClient-PM3U6Q6J.js → cliAuthorityBrokerClient-XHH7MH2P.js} +1 -1
- package/{cliAuthorityStoreDriver-TKLXNNTG.js → cliAuthorityStoreDriver-6FE3BJNB.js} +1 -1
- package/{cliEnvHelpers-BVYTMUPJ.js → cliEnvHelpers-VPSJ4XWC.js} +3 -3
- package/{cliExecutor-BWBF2MTI.js → cliExecutor-4MAX3PZL.js} +2 -2
- package/cliLocalAgentRecordReader-MHHD4T7R.js +90 -0
- package/{commandRegistry-W63CYRZJ.js → commandRegistry-5DA5UP7S.js} +105 -97
- package/{contentThunks-U7PL5MQD.js → contentThunks-5GUQ7FWJ.js} +47 -43
- package/{cooldownCommands-TIGUHXTD.js → cooldownCommands-X7P5M2V5.js} +5 -4
- package/{createAgentAutomationAction-OLBQDD6R.js → createAgentAutomationAction-UCLTHQRI.js} +51 -49
- package/{createDialogAction-SVH6B3SB.js → createDialogAction-UPN774AF.js} +46 -48
- package/{createPageAction-F4DIWZ2Z.js → createPageAction-JRQ2TA4O.js} +50 -48
- package/{cursorProvider-YGGNMVWX.js → cursorProvider-2RACMEMF.js} +1 -1
- package/{db-HUCI5R4G.js → db-CS4ZJQKV.js} +1 -1
- package/{dbSlice-BVH2YZPQ.js → dbSlice-WNON7TOL.js} +17 -16
- package/{deleteFile-5YOEKV4U.js → deleteFile-Q3YDB4ML.js} +9 -9
- package/{desktopFolderProjects-SFY5EZS3.js → desktopFolderProjects-4POAMVJN.js} +2 -2
- package/{dialogCommands-KHIEPY3M.js → dialogCommands-VRI7VCXH.js} +64 -57
- package/dialogNotifyCommand-6TMCX4D2.js +36 -0
- package/{dialogSlice-ZCTDV2PZ.js → dialogSlice-LFNVUSAN.js} +42 -40
- package/{dialogUsageCommand-7KCPYGHG.js → dialogUsageCommand-HTVPR2CX.js} +11 -10
- package/{docCreateCommands-DPMZI7G5.js → docCreateCommands-AMPXMOX3.js} +61 -55
- package/{docDeleteCommands-IRQQLUBT.js → docDeleteCommands-I5WFAEHP.js} +63 -57
- package/{docReadCommands-LK37XH6L.js → docReadCommands-X53ELNIE.js} +61 -55
- package/{docStore-V2KECILA.js → docStore-2VAWVLWH.js} +21 -20
- package/{docUpdateCommands-O6T3HJHH.js → docUpdateCommands-6QPNDC7M.js} +64 -58
- package/{fetchMessages-NR4KNQLO.js → fetchMessages-TQEUZD7H.js} +8 -7
- package/{getPricing-2MNMXEVG.js → getPricing-MB2GBXOK.js} +6 -6
- package/{handleSendMessageAction-2PE25WM3.js → handleSendMessageAction-AAJOHXOB.js} +194 -302
- package/{hostCredentialCreate-S233UMAP.js → hostCredentialCreate-GLMJ22M6.js} +123 -114
- package/index.js +29 -29
- package/{keys-BEGDOTRL.js → keys-RWF7UCB4.js} +5 -4
- package/legacyMigration-TF4SYJCZ.js +19 -0
- package/{lib-5KKIBFIT.js → lib-OT5OTXRU.js} +7087 -6664
- package/{localDialogRead-7NNDVVF7.js → localDialogRead-SVTPA5GY.js} +3 -3
- package/{localFirstLog-DHNOY2NA.js → localFirstLog-OIETGK66.js} +1 -1
- package/localRecall-2J6QPOK2.js +15 -0
- package/{localRuntimeAdapter-KY6WXNBR.js → localRuntimeAdapter-BMP57P42.js} +119 -110
- package/{localRuntimeAuthority-OYH4AE4G.js → localRuntimeAuthority-IBJAT62G.js} +1 -1
- package/{localRuntimeDb-VBIMCWUC.js → localRuntimeDb-N7KHDXS2.js} +2 -2
- package/{machineCommands-Q6HA3IXF.js → machineCommands-3MLIAK5Q.js} +128 -119
- package/{machineInfo-UKPTZO5Y.js → machineInfo-LWHTEBHJ.js} +1 -1
- package/machineWsRunDispatch-FKIGROQF.js +191 -0
- package/{memberThunks-7EDJADWU.js → memberThunks-ZGLZ36PK.js} +29 -28
- package/{memoryCommands-ASCE5STX.js → memoryCommands-5WC3T66U.js} +4 -4
- package/models-ULVWLSQ6.js +9 -0
- package/{oauthTokenStore-OEERZFUC.js → oauthTokenStore-RUYNYALS.js} +1 -1
- package/{offlineMarxistsAgentCommand-2QTHJCHV.js → offlineMarxistsAgentCommand-4IC3Y4C6.js} +4 -4
- package/overlay-THLKYIWY.js +11 -0
- package/package.json +2 -2
- package/{pdf-U6KSUEZZ.js → pdf-KE3QI2V7.js} +1 -1
- package/{processSpawn-ZU5QFM43.js → processSpawn-6GEO77KV.js} +1 -1
- package/{profileConfig-KN3N2BLF.js → profileConfig-KOWK4HOG.js} +1 -1
- package/{projectArchive-DRTDIMEV.js → projectArchive-HK63GMF4.js} +52 -50
- package/{providerPresetApply-YXGV6NXB.js → providerPresetApply-OIFQ73LH.js} +19 -12
- package/{providerRegistry-S6UL6UNA.js → providerRegistry-KZ3SDZ3D.js} +10 -10
- package/{read-4V2RMG7N.js → read-MRQHJMJ2.js} +10 -10
- package/{readDocTool-BH6ATGQO.js → readDocTool-4BGTXTXA.js} +2 -2
- package/{readlineWorkspace-2W4WRCOU.js → readlineWorkspace-AKAHSCNY.js} +7982 -6274
- package/{removeDialogAgentAction-LYAZGNKW.js → removeDialogAgentAction-B6H7DXFM.js} +23 -22
- package/{runAgentClientLoop-J2VQBS2Z.js → runAgentClientLoop-UVAWGEON.js} +81 -79
- package/{runtimeDoctorCommands-QAI3MBKQ.js → runtimeDoctorCommands-FW6XKDUG.js} +12 -12
- package/{runtimeModeArgs-2Y7BALTO.js → runtimeModeArgs-X7DL7PUN.js} +1 -1
- package/secretCommands-LJXOOYA7.js +24 -0
- package/{setDialogExtraReferencesAction-OCRPGPYH.js → setDialogExtraReferencesAction-EVCY3TRW.js} +22 -21
- package/{setPrimaryDialogAgentAction-HFJDQIBU.js → setPrimaryDialogAgentAction-KPFVPHCJ.js} +23 -22
- package/{settingThunks-RAMHMTGM.js → settingThunks-ENOAK2WV.js} +97 -88
- package/{skillDiscovery-XKHROSH2.js → skillDiscovery-B5V23AXP.js} +4 -4
- package/{skillSummaryMarker-42HKSXYY.js → skillSummaryMarker-62UW7HI7.js} +1 -1
- package/{slateToRenderMarkdown-Y5IYN73U.js → slateToRenderMarkdown-R3X74MCX.js} +1 -1
- package/{slateUtils-NGV2NMKM.js → slateUtils-ESQAJ6RN.js} +1 -1
- package/{spaceCommands-KVJZVKVO.js → spaceCommands-DTTNAS2L.js} +61 -53
- package/store-JRVN62NM.js +46 -0
- package/{streamAgentChatTurn-GHBMJJ6S.js → streamAgentChatTurn-R5UY25VB.js} +875 -618
- package/{switchDialogAgentAction-EBRMW3RA.js → switchDialogAgentAction-SZ44XDRY.js} +21 -20
- package/{tableCommands-MP6VFSVT.js → tableCommands-HITDSLHS.js} +10 -10
- package/tombstones-FQQMEDOW.js +32 -0
- package/{toolApiClient-HGNO53TC.js → toolApiClient-OGQEBQVX.js} +4 -4
- package/{tools-EWKCPKMS.js → tools-HWFG6GMJ.js} +75 -74
- package/tuiSummaryLlmCaller-HQQZAMYF.js +44 -0
- package/{updateCommands-ZQYU6SCI.js → updateCommands-RJVCRSBP.js} +10 -8
- package/{updateDialogTitleAction-5GGMBTDF.js → updateDialogTitleAction-KNPOAMVS.js} +48 -46
- package/{usageCommand-F4IPVMIZ.js → usageCommand-FWZCB7AM.js} +11 -10
- package/{usageRebuildCommand-HAW2AD5N.js → usageRebuildCommand-SP2BLNJU.js} +12 -11
- package/userDataMerge-HT2ZVHBJ.js +13 -0
- package/{windowsSelfUpdate-257DV2T6.js → windowsSelfUpdate-KERHIAB4.js} +3 -3
- package/{workloadLifecycle-4C42SVBD.js → workloadLifecycle-DYNEYHV5.js} +6 -6
- package/agentRecordCommands-ZQ7SVYGG.js +0 -167
- package/agentRunCommand-WS7IGO2W.js +0 -196
- package/chunk-3CGG2PAL.js +0 -594
- package/chunk-5XBUWM6I.js +0 -89
- package/chunk-CJEIOP3E.js +0 -0
- package/chunk-EHGEOAHI.js +0 -636
- package/chunk-FW6YHHLI.js +0 -842
- package/chunk-GPVRUGGY.js +0 -115
- package/chunk-HSVBJRF4.js +0 -339
- package/chunk-WJZOQR2J.js +0 -151
- package/chunk-ZCWRMUWT.js +0 -89
- package/dist-M676ULYG.js +0 -7314
- package/machineWsRunDispatch-WWJQ6WR3.js +0 -182
- package/models-PJBE6JDV.js +0 -9
- package/tuiSummaryLlmCaller-ALQYUUWB.js +0 -189
- package/{chunk-WACI5I6V.js → chunk-2THCNKE4.js} +3 -3
- package/{chunk-2QHFH3DR.js → chunk-47ITIXO7.js} +6 -6
- package/{chunk-GOO6G4PY.js → chunk-CKG3PRZ7.js} +0 -0
- package/{chunk-OQHIVPG4.js → chunk-SNBZZPYH.js} +3 -3
- package/{chunk-AETZ7AD6.js → chunk-W6RFEDN4.js} +3 -3
|
@@ -1,20 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
applyChatCompletionDelta,
|
|
3
|
-
applyResponsesToolEvent,
|
|
4
|
-
createResponsesToolAccumulator,
|
|
5
|
-
finalizeResponsesToolCalls,
|
|
6
|
-
flushChatCompletionStream,
|
|
7
|
-
providerHttpFailure,
|
|
8
|
-
throwIfChatCompletionStreamFailed
|
|
9
|
-
} from "./chunk-OQPKUBPB.js";
|
|
10
1
|
import {
|
|
11
2
|
DEVIN_CONNECT_URL,
|
|
12
3
|
parseSseDataLineJson,
|
|
13
4
|
parseSseDataLineObject
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import {
|
|
16
|
-
readSseFrames
|
|
17
|
-
} from "./chunk-HNUWUO75.js";
|
|
5
|
+
} from "./chunk-3LMUPOHG.js";
|
|
18
6
|
import {
|
|
19
7
|
evaluateFileWritePolicy,
|
|
20
8
|
summarizeToolArguments
|
|
@@ -25,11 +13,36 @@ import {
|
|
|
25
13
|
import {
|
|
26
14
|
formatImageSummary,
|
|
27
15
|
readLocalImage
|
|
28
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-AL3TYDIF.js";
|
|
17
|
+
import {
|
|
18
|
+
applyChatCompletionDelta,
|
|
19
|
+
applyResponsesToolEvent,
|
|
20
|
+
createResponsesToolAccumulator,
|
|
21
|
+
finalizeResponsesToolCalls,
|
|
22
|
+
flushChatCompletionStream,
|
|
23
|
+
providerHttpFailure,
|
|
24
|
+
throwIfChatCompletionStreamFailed
|
|
25
|
+
} from "./chunk-QNWG52I4.js";
|
|
26
|
+
import {
|
|
27
|
+
readSseFrames
|
|
28
|
+
} from "./chunk-HNUWUO75.js";
|
|
29
29
|
import {
|
|
30
|
+
resolveToolExecutionContract
|
|
31
|
+
} from "./chunk-LKA64WH4.js";
|
|
32
|
+
import {
|
|
33
|
+
evaluateRequestBudget,
|
|
30
34
|
hasImageInRuntimeMessages,
|
|
31
35
|
stripImagePartsFromMessages
|
|
32
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-YU4ZPWVF.js";
|
|
37
|
+
import {
|
|
38
|
+
clipToolText,
|
|
39
|
+
resolveHistoricalToolContentCap,
|
|
40
|
+
resolveToolOutputProfile
|
|
41
|
+
} from "./chunk-2WZXXAQD.js";
|
|
42
|
+
import {
|
|
43
|
+
resolveAgentImageInputSupport,
|
|
44
|
+
resolveToolImagePolicy
|
|
45
|
+
} from "./chunk-OBWT45ZU.js";
|
|
33
46
|
import {
|
|
34
47
|
applyShapingCounts,
|
|
35
48
|
attachProjectionFacts,
|
|
@@ -40,7 +53,7 @@ import {
|
|
|
40
53
|
projectUserPartForModel,
|
|
41
54
|
resolveOutboundDiagnosticSink,
|
|
42
55
|
writeThinkingFacts
|
|
43
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-BGP2EDFG.js";
|
|
44
57
|
import {
|
|
45
58
|
createThinkParserState,
|
|
46
59
|
createToolCallAccumulator,
|
|
@@ -66,7 +79,25 @@ import {
|
|
|
66
79
|
hashStablePrefixContent,
|
|
67
80
|
resolveResponseGuidelines,
|
|
68
81
|
resolveToolGuidedSections
|
|
69
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-EIAI3PPH.js";
|
|
83
|
+
import {
|
|
84
|
+
BRIDGE_STREAM_MAX_CHARS,
|
|
85
|
+
CLI_NOLO_WORKSPACE_TOOL_NAMES,
|
|
86
|
+
DEFAULT_READ_DIALOG_MAX_RESPONSE_CHARS,
|
|
87
|
+
NOLO_WORKSPACE_TOOL_NAMES,
|
|
88
|
+
buildDialogReadEnvelope,
|
|
89
|
+
buildNoloWorkspaceCommandArgs,
|
|
90
|
+
buildNoloWorkspaceOpenAiTools,
|
|
91
|
+
createStreamingDialogReadProjector,
|
|
92
|
+
noloPositiveIntegerString,
|
|
93
|
+
noloStringArg,
|
|
94
|
+
parseNoloWorkspaceToolArguments,
|
|
95
|
+
readTextStreamUpToChars,
|
|
96
|
+
resolveNoloDialogInput
|
|
97
|
+
} from "./chunk-C4VAR65S.js";
|
|
98
|
+
import {
|
|
99
|
+
applyToolSurfaceConstraints
|
|
100
|
+
} from "./chunk-SOF4OWDM.js";
|
|
70
101
|
import {
|
|
71
102
|
classifyUnparsableToolArgs,
|
|
72
103
|
collectStablePromptPrefix,
|
|
@@ -90,7 +121,7 @@ import {
|
|
|
90
121
|
toOpenAiCompatibleMessages,
|
|
91
122
|
toResponsesTools,
|
|
92
123
|
transferDowngradedToolTurnOrigin
|
|
93
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-MAIITKBT.js";
|
|
94
125
|
import {
|
|
95
126
|
TOOL_HAD_IMAGES,
|
|
96
127
|
TOOL_IMAGES,
|
|
@@ -105,37 +136,11 @@ import {
|
|
|
105
136
|
withoutToolImages
|
|
106
137
|
} from "./chunk-E2BESSAW.js";
|
|
107
138
|
import {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
DEFAULT_READ_DIALOG_MAX_RESPONSE_CHARS,
|
|
111
|
-
DEFAULT_SUBTASK_MAX_TOOL_CALLS,
|
|
112
|
-
DEFAULT_SUBTASK_MAX_WALL_CLOCK_MS,
|
|
113
|
-
NOLO_WORKSPACE_TOOL_NAMES,
|
|
114
|
-
buildDialogReadEnvelope,
|
|
115
|
-
buildNoloWorkspaceCommandArgs,
|
|
116
|
-
buildNoloWorkspaceOpenAiTools,
|
|
117
|
-
buildSubtaskBudgetExhaustedContent,
|
|
118
|
-
createStreamingDialogReadProjector,
|
|
119
|
-
createSubtaskBudgetTracker,
|
|
120
|
-
noloPositiveIntegerString,
|
|
121
|
-
noloStringArg,
|
|
122
|
-
parseNoloWorkspaceToolArguments,
|
|
123
|
-
readTextStreamUpToChars,
|
|
124
|
-
resolveNoloDialogInput
|
|
125
|
-
} from "./chunk-RZOV7OMV.js";
|
|
126
|
-
import {
|
|
127
|
-
applyToolSurfaceConstraints
|
|
128
|
-
} from "./chunk-KC4XDTT3.js";
|
|
129
|
-
import {
|
|
130
|
-
clipToolText,
|
|
131
|
-
planContextUsage,
|
|
132
|
-
resolveHistoricalToolContentCap,
|
|
133
|
-
resolveToolOutputProfile
|
|
134
|
-
} from "./chunk-YB3YZK56.js";
|
|
139
|
+
isQuotaExhaustedError
|
|
140
|
+
} from "./chunk-TLE77UJ5.js";
|
|
135
141
|
import {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
} from "./chunk-YWSEPJ7C.js";
|
|
142
|
+
isAgentSkillDisabled
|
|
143
|
+
} from "./chunk-FS2XP5D7.js";
|
|
139
144
|
import {
|
|
140
145
|
buildDialogFallbackTitleFromUserInput
|
|
141
146
|
} from "./chunk-2MBTWINN.js";
|
|
@@ -143,29 +148,34 @@ import {
|
|
|
143
148
|
EMPTY_ASSISTANT_REPAIR_PROMPT,
|
|
144
149
|
extractReferenceKeysFromMessage,
|
|
145
150
|
hasAssistantVisibleOutput,
|
|
146
|
-
normalizeUsage,
|
|
147
|
-
readCacheCreationInputTokens,
|
|
148
|
-
readCacheReadInputTokens,
|
|
149
151
|
resolveAgentContextWindow,
|
|
150
152
|
resolveEmptyAssistantFallbackMessage,
|
|
151
153
|
resolveEmptyAssistantOutcome,
|
|
152
154
|
resolveTruncatedReasoningTailLog
|
|
153
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-NIZ2BXFD.js";
|
|
154
156
|
import {
|
|
155
157
|
COMPACTION_SUMMARY_SCHEMA_VERSION,
|
|
156
158
|
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|
|
157
159
|
buildBoundedCompactionRequest,
|
|
158
160
|
buildCompactionMetricsFromPlan,
|
|
161
|
+
classifySummaryError,
|
|
159
162
|
computeSummarySourceMetadata,
|
|
163
|
+
createSummaryBudget,
|
|
160
164
|
formatCompactionMetricsLog,
|
|
161
165
|
getMessageTokenCount,
|
|
162
166
|
getModelContextWindow,
|
|
167
|
+
isTruncatedCompletion,
|
|
168
|
+
normalizeUsage,
|
|
163
169
|
planCompression,
|
|
170
|
+
readCacheCreationInputTokens,
|
|
171
|
+
readCacheReadInputTokens,
|
|
164
172
|
resolveCompressionTriggerRatio,
|
|
165
173
|
resolveEffectiveCompactionBudgets,
|
|
174
|
+
runSummaryWithContract,
|
|
166
175
|
sha256Hex,
|
|
176
|
+
summaryCompletionTokens,
|
|
167
177
|
truncateToolOutputForContext
|
|
168
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-RDH5CQ4T.js";
|
|
169
179
|
import {
|
|
170
180
|
createProviderCallTimingTracker,
|
|
171
181
|
finalizeProviderCallTiming,
|
|
@@ -176,25 +186,38 @@ import {
|
|
|
176
186
|
import {
|
|
177
187
|
clipCompactText
|
|
178
188
|
} from "./chunk-5MMAK75Q.js";
|
|
179
|
-
import {
|
|
180
|
-
assertCredentialRef
|
|
181
|
-
} from "./chunk-OQHIVPG4.js";
|
|
182
189
|
import {
|
|
183
190
|
asRecordOrEmpty
|
|
184
191
|
} from "./chunk-KX6YBIHG.js";
|
|
192
|
+
import {
|
|
193
|
+
assertCredentialRef
|
|
194
|
+
} from "./chunk-SNBZZPYH.js";
|
|
195
|
+
import {
|
|
196
|
+
isLevelNotFoundError
|
|
197
|
+
} from "./chunk-OW765XBU.js";
|
|
185
198
|
import {
|
|
186
199
|
isAbortError
|
|
187
200
|
} from "./chunk-7DPNBQSV.js";
|
|
188
201
|
import {
|
|
189
|
-
|
|
190
|
-
} from "./chunk-
|
|
191
|
-
import {
|
|
192
|
-
buildUserResponseLanguageContext
|
|
193
|
-
} from "./chunk-4VJAC32I.js";
|
|
202
|
+
WORKTREE_ISOLATION_PRELUDE
|
|
203
|
+
} from "./chunk-PJCIP64Z.js";
|
|
194
204
|
import {
|
|
195
205
|
canonicalizeToolName,
|
|
196
206
|
canonicalizeToolNames
|
|
197
|
-
} from "./chunk-
|
|
207
|
+
} from "./chunk-6OVNSQHN.js";
|
|
208
|
+
import {
|
|
209
|
+
dialogMessageKey,
|
|
210
|
+
dialogMessageRange
|
|
211
|
+
} from "./chunk-OJKUU3LP.js";
|
|
212
|
+
import {
|
|
213
|
+
asTrimmedNonEmptyStringArray
|
|
214
|
+
} from "./chunk-I42VC5KR.js";
|
|
215
|
+
import {
|
|
216
|
+
buildDialogSummaryLayer
|
|
217
|
+
} from "./chunk-JWXITTQB.js";
|
|
218
|
+
import {
|
|
219
|
+
buildUserResponseLanguageContext
|
|
220
|
+
} from "./chunk-L5I543VB.js";
|
|
198
221
|
import {
|
|
199
222
|
buildInteractiveCommandBlockedResult,
|
|
200
223
|
buildProcessTaskResultCapsule,
|
|
@@ -209,56 +232,54 @@ import {
|
|
|
209
232
|
formatToolOverflowMarker,
|
|
210
233
|
getProcessRegistry,
|
|
211
234
|
isProcessTaskTerminalStatus,
|
|
235
|
+
isSpilledToolOutput,
|
|
212
236
|
reportedTaskStatus,
|
|
213
237
|
resolveExecShellTimeoutMs,
|
|
214
238
|
resolveExecutableOnPath,
|
|
215
239
|
runWorkspaceCommand,
|
|
216
240
|
spawnToWebStreams,
|
|
241
|
+
spillLargeToolOutput,
|
|
217
242
|
spillToolOutput,
|
|
218
243
|
toProcessTaskView,
|
|
219
244
|
truncateToolOutput
|
|
220
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-KEN3N2TN.js";
|
|
221
246
|
import {
|
|
222
247
|
estimateTokenCount
|
|
223
248
|
} from "./chunk-PSCNXBYA.js";
|
|
224
249
|
import {
|
|
225
250
|
buildProviderAuthHeaders,
|
|
226
251
|
buildProviderExecutionPlan
|
|
227
|
-
} from "./chunk-
|
|
252
|
+
} from "./chunk-I7WBYGBP.js";
|
|
228
253
|
import {
|
|
229
254
|
toErrorMessage
|
|
230
255
|
} from "./chunk-HNMXYYJR.js";
|
|
256
|
+
import {
|
|
257
|
+
asTrimmedString
|
|
258
|
+
} from "./chunk-3EUW3WEO.js";
|
|
231
259
|
import {
|
|
232
260
|
isRecord
|
|
233
261
|
} from "./chunk-KUG52IAP.js";
|
|
262
|
+
import {
|
|
263
|
+
PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL
|
|
264
|
+
} from "./chunk-CKG3PRZ7.js";
|
|
234
265
|
import {
|
|
235
266
|
asTrimmedLowercaseString
|
|
236
267
|
} from "./chunk-QSJ3HFEF.js";
|
|
237
|
-
import {
|
|
238
|
-
normalizeServerOrigin
|
|
239
|
-
} from "./chunk-CF7PE763.js";
|
|
240
|
-
import {
|
|
241
|
-
resolveNoloStateDir
|
|
242
|
-
} from "./chunk-6UBGXX2W.js";
|
|
243
|
-
import {
|
|
244
|
-
dialogMessageKey,
|
|
245
|
-
dialogMessageRange
|
|
246
|
-
} from "./chunk-XJWWBO34.js";
|
|
247
|
-
import {
|
|
248
|
-
asTrimmedNonEmptyStringArray
|
|
249
|
-
} from "./chunk-I42VC5KR.js";
|
|
250
268
|
import {
|
|
251
269
|
asOptionalPositiveFiniteNumber
|
|
252
270
|
} from "./chunk-U6VC4MU4.js";
|
|
253
|
-
import {
|
|
254
|
-
asTrimmedString
|
|
255
|
-
} from "./chunk-3EUW3WEO.js";
|
|
256
271
|
import {
|
|
257
272
|
asOptionalTrimmedString
|
|
258
273
|
} from "./chunk-G3SUCT4W.js";
|
|
274
|
+
import {
|
|
275
|
+
normalizeServerOrigin
|
|
276
|
+
} from "./chunk-CF7PE763.js";
|
|
277
|
+
import {
|
|
278
|
+
resolveNoloStateDir
|
|
279
|
+
} from "./chunk-6UBGXX2W.js";
|
|
259
280
|
import {
|
|
260
281
|
__export
|
|
261
|
-
} from "./chunk-
|
|
282
|
+
} from "./chunk-U67V476Y.js";
|
|
262
283
|
|
|
263
284
|
// packages/agent-runtime/actionGate.ts
|
|
264
285
|
function readCommandActionGatePayload(payload) {
|
|
@@ -302,6 +323,42 @@ function readTitleParams(value) {
|
|
|
302
323
|
return Object.fromEntries(entries);
|
|
303
324
|
}
|
|
304
325
|
|
|
326
|
+
// packages/agent-runtime/contextRefusal.ts
|
|
327
|
+
var machineIdentifier = (value) => value && /^[A-Z][A-Z0-9_]{0,63}$/.test(value) ? value : void 0;
|
|
328
|
+
function classifyContextRefusal(args2) {
|
|
329
|
+
const { outcome, historyTokens, budget, droppedCount } = args2;
|
|
330
|
+
const largest = args2.largestMessageTokens;
|
|
331
|
+
const numbersKnown = Number.isFinite(historyTokens) && historyTokens >= 0 && Number.isFinite(budget) && budget >= 0 && largest !== void 0 && Number.isFinite(largest) && largest >= 0;
|
|
332
|
+
const base = { historyTokens, budget, droppedCount, largestMessageTokens: largest ?? -1 };
|
|
333
|
+
const result4 = (reason, detail) => ({ ...base, reason, detail });
|
|
334
|
+
if (!numbersKnown) return result4("unknown", "input-estimate-unavailable");
|
|
335
|
+
if (largest >= budget) return result4("single-message-too-large", "largest-message-at-or-above-budget");
|
|
336
|
+
const compacted = outcome?.result;
|
|
337
|
+
const decision = compacted?.decision;
|
|
338
|
+
const failure = outcome?.error ?? compacted?.failure;
|
|
339
|
+
if (failure || compacted?.failureReason || decision?.outcome === "failed") {
|
|
340
|
+
const code = machineIdentifier(failure?.code);
|
|
341
|
+
const errorType = failure?.errorType;
|
|
342
|
+
const status = failure?.status;
|
|
343
|
+
if (code === "PROVIDER_UNAVAILABLE" || code === "SUMMARY_PROVIDER_UNAVAILABLE") {
|
|
344
|
+
return result4("no-compactable-content", `code=${code}`);
|
|
345
|
+
}
|
|
346
|
+
const busy = status === 503 || status === 429 || !!code && /BUSY|RATE_LIMIT|CAPACITY|OVERLOAD|RESOURCE_EXHAUSTED/.test(code) || !!errorType && /^(?:capacity|overloaded|rate_limit)(?:_error)?$/.test(errorType);
|
|
347
|
+
const detail = [
|
|
348
|
+
status !== void 0 && Number.isInteger(status) && status >= 100 && status <= 599 ? `status=${status}` : "",
|
|
349
|
+
code ? `code=${code}` : "",
|
|
350
|
+
failure ? `category=${failure.category}` : `failure=${compacted?.failureReason ?? (decision?.outcome === "failed" ? decision.reason : "provider-error")}`
|
|
351
|
+
].filter(Boolean).join(" ");
|
|
352
|
+
return result4(busy ? "summary-provider-busy" : "summary-failed", detail);
|
|
353
|
+
}
|
|
354
|
+
if (decision?.outcome === "skipped") {
|
|
355
|
+
if (decision.skipReason === "summary-empty") return result4("summary-failed", "summary-empty");
|
|
356
|
+
const bounded3 = decision.skipReason === "bounded-request-blocked" ? /\b(no-budget|invalid-window|empty-input|no-safe-group|group-too-large)\b/.exec(decision.detail ?? "")?.[1] : void 0;
|
|
357
|
+
return result4("no-compactable-content", `skip=${decision.skipReason}${bounded3 ? ` detail=${bounded3}` : ""}`);
|
|
358
|
+
}
|
|
359
|
+
return result4("unknown", decision ? "no-refusal-decision" : "compaction-not-evaluated");
|
|
360
|
+
}
|
|
361
|
+
|
|
305
362
|
// node_modules/effect/dist/Pipeable.js
|
|
306
363
|
var pipeArguments = (self, args2) => {
|
|
307
364
|
switch (args2.length) {
|
|
@@ -13125,6 +13182,30 @@ function createLoopTiming() {
|
|
|
13125
13182
|
return { mark, flush: flush2 };
|
|
13126
13183
|
}
|
|
13127
13184
|
|
|
13185
|
+
// packages/agent-runtime/toolExecutionFailure.ts
|
|
13186
|
+
function isToolExecutionFailure(args2) {
|
|
13187
|
+
const metadata = args2.metadata;
|
|
13188
|
+
if (metadata) {
|
|
13189
|
+
if (metadata.error) return true;
|
|
13190
|
+
const exitCode = metadata.exitCode;
|
|
13191
|
+
if (typeof exitCode === "number" && Number.isFinite(exitCode) && exitCode !== 0) return true;
|
|
13192
|
+
if (typeof exitCode === "string" && exitCode.trim() !== "") {
|
|
13193
|
+
const parsedExitCode = Number(exitCode);
|
|
13194
|
+
if (Number.isFinite(parsedExitCode) && parsedExitCode !== 0) return true;
|
|
13195
|
+
}
|
|
13196
|
+
if (metadata.timedOut === true) return true;
|
|
13197
|
+
}
|
|
13198
|
+
if (typeof args2.content !== "string" || !args2.content.trim()) return false;
|
|
13199
|
+
try {
|
|
13200
|
+
const parsed = JSON.parse(args2.content);
|
|
13201
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return false;
|
|
13202
|
+
const record2 = parsed;
|
|
13203
|
+
return Boolean(record2.error) || record2.ok === false || record2.success === false || record2.status === "error";
|
|
13204
|
+
} catch {
|
|
13205
|
+
return false;
|
|
13206
|
+
}
|
|
13207
|
+
}
|
|
13208
|
+
|
|
13128
13209
|
// packages/agent-runtime/toolCallPairing.ts
|
|
13129
13210
|
function readToolCallId(message) {
|
|
13130
13211
|
if (typeof message.tool_call_id === "string" && message.tool_call_id) {
|
|
@@ -13483,7 +13564,7 @@ var OBSERVATION_ONLY_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
|
13483
13564
|
]);
|
|
13484
13565
|
function formatToolMessageContent(args2) {
|
|
13485
13566
|
const sanitizedContent = sanitizeToolOutputText(args2.content ?? "");
|
|
13486
|
-
const scrubbedContent = scrubSecrets(sanitizedContent).cleaned;
|
|
13567
|
+
const scrubbedContent = spillLargeToolOutput(scrubSecrets(sanitizedContent).cleaned, args2.toolName, args2.workspaceRoot);
|
|
13487
13568
|
if (args2.toolName !== "globFiles" && args2.toolName !== "codeSearch" && args2.toolName !== "readFile" || !args2.metadata || Object.keys(args2.metadata).length === 0) {
|
|
13488
13569
|
return scrubbedContent;
|
|
13489
13570
|
}
|
|
@@ -13499,7 +13580,7 @@ function formatToolMessageContent(args2) {
|
|
|
13499
13580
|
[tool metadata]
|
|
13500
13581
|
${JSON.stringify(visible)}`;
|
|
13501
13582
|
}
|
|
13502
|
-
function blocksToOpenAiMessages(blocks) {
|
|
13583
|
+
function blocksToOpenAiMessages(blocks, workspaceRoot) {
|
|
13503
13584
|
const out = [];
|
|
13504
13585
|
let text2 = "";
|
|
13505
13586
|
let reasoning = "";
|
|
@@ -13520,6 +13601,7 @@ function blocksToOpenAiMessages(blocks) {
|
|
|
13520
13601
|
role: "tool",
|
|
13521
13602
|
content: formatToolMessageContent({
|
|
13522
13603
|
toolName: tc.function.name,
|
|
13604
|
+
workspaceRoot,
|
|
13523
13605
|
content: res?.content ?? "",
|
|
13524
13606
|
...res?.metadata ? { metadata: res.metadata } : {}
|
|
13525
13607
|
}),
|
|
@@ -13586,42 +13668,6 @@ var TOOL_METADATA_KEYS = [
|
|
|
13586
13668
|
"pasteId",
|
|
13587
13669
|
"source"
|
|
13588
13670
|
];
|
|
13589
|
-
function trimHistoryToContextBudget(history, model, contextWindowOverride) {
|
|
13590
|
-
if (history.length === 0) return { history, droppedCount: 0 };
|
|
13591
|
-
const { rawMessageBudget } = planContextUsage({
|
|
13592
|
-
contextWindow: contextWindowOverride ?? getModelContextWindow(model ?? ""),
|
|
13593
|
-
summaryTokens: 0,
|
|
13594
|
-
// localLoop 没有 web 端的负载分档器;medium 是中性默认值,
|
|
13595
|
-
// 不为了省几个 token 在这里复制一份分类逻辑。
|
|
13596
|
-
recentLoad: "medium"
|
|
13597
|
-
});
|
|
13598
|
-
const messageTokens = (message) => {
|
|
13599
|
-
const toolCalls = message.tool_calls;
|
|
13600
|
-
return estimateTokenCount(contentAsText(message.content)) + (Array.isArray(toolCalls) ? estimateTokenCount(JSON.stringify(toolCalls)) : 0);
|
|
13601
|
-
};
|
|
13602
|
-
let used = 0;
|
|
13603
|
-
let start = history.length;
|
|
13604
|
-
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
13605
|
-
const cost = messageTokens(history[i]);
|
|
13606
|
-
if (used + cost > rawMessageBudget && start < history.length) break;
|
|
13607
|
-
used += cost;
|
|
13608
|
-
start = i;
|
|
13609
|
-
}
|
|
13610
|
-
if (start === 0) return { history, droppedCount: 0 };
|
|
13611
|
-
return {
|
|
13612
|
-
history: sanitizeToolCallPairing(history.slice(start)),
|
|
13613
|
-
droppedCount: start
|
|
13614
|
-
};
|
|
13615
|
-
}
|
|
13616
|
-
function contentAsText(content) {
|
|
13617
|
-
if (typeof content === "string") return content;
|
|
13618
|
-
if (!Array.isArray(content)) return "";
|
|
13619
|
-
return content.map((part) => {
|
|
13620
|
-
if (part?.type === "text") return part.text;
|
|
13621
|
-
if (part?.type === "image_url") return part.image_url.url;
|
|
13622
|
-
return "";
|
|
13623
|
-
}).join("\n");
|
|
13624
|
-
}
|
|
13625
13671
|
function contentCharCount(content) {
|
|
13626
13672
|
if (typeof content === "string") return content.length;
|
|
13627
13673
|
if (!Array.isArray(content)) return 0;
|
|
@@ -13655,6 +13701,7 @@ function projectToolContentForProvider(args2) {
|
|
|
13655
13701
|
const rawContent = args2.content;
|
|
13656
13702
|
const content = typeof rawContent === "string" ? sanitizeToolOutputText(rawContent) : rawContent;
|
|
13657
13703
|
if (typeof content !== "string") return content;
|
|
13704
|
+
if (isSpilledToolOutput(content)) return content;
|
|
13658
13705
|
const metadataText = compactToolMetadata(args2.metadata);
|
|
13659
13706
|
const embeddedMetadataIndex = metadataText ? content.indexOf("\n\n[tool metadata]\n") : -1;
|
|
13660
13707
|
const contentForProjection = embeddedMetadataIndex >= 0 ? content.slice(0, embeddedMetadataIndex) : content;
|
|
@@ -13686,7 +13733,7 @@ ${metadataText}` : "";
|
|
|
13686
13733
|
content: contentForProjection,
|
|
13687
13734
|
toolName: args2.toolName
|
|
13688
13735
|
});
|
|
13689
|
-
spillNote = `; spillFile=${spill.displayPath}; totalLines=${spill.totalLines}; hint=read full
|
|
13736
|
+
spillNote = `; spillFile=${spill.displayPath}; totalLines=${spill.totalLines}; hint=read a range, not the whole spill (readFile lines=A-B or sed -n 'A,Bp'); a full read re-injects ${spill.totalChars} chars`;
|
|
13690
13737
|
} catch {
|
|
13691
13738
|
}
|
|
13692
13739
|
}
|
|
@@ -13896,6 +13943,29 @@ ${args2.input}` : [
|
|
|
13896
13943
|
} : {}
|
|
13897
13944
|
};
|
|
13898
13945
|
}
|
|
13946
|
+
function estimateLocalRequestInput(messages, toolSchemaTokens = 0) {
|
|
13947
|
+
return messages.reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0) + toolSchemaTokens;
|
|
13948
|
+
}
|
|
13949
|
+
function evaluateLocalRequestBudget(args2) {
|
|
13950
|
+
const estimate = estimateLocalRequestInput(args2.messages, args2.descriptor?.toolSchemaTokens ?? 0);
|
|
13951
|
+
const ratio = Math.max(1, args2.calibrationRatio ?? 1);
|
|
13952
|
+
const output = args2.descriptor?.output ?? { semantics: "unknown", fallbackReserveTokens: 8192 };
|
|
13953
|
+
const boundedOutput = output.semantics === "unknown" ? { ...output, fallbackReserveTokens: Math.min(
|
|
13954
|
+
output.fallbackReserveTokens,
|
|
13955
|
+
Math.min(8192, Math.max(1, Math.floor(args2.contextWindow / 4)))
|
|
13956
|
+
) } : output;
|
|
13957
|
+
return evaluateRequestBudget({
|
|
13958
|
+
contextWindow: args2.contextWindow,
|
|
13959
|
+
messageTokens: Math.ceil(estimate * ratio),
|
|
13960
|
+
toolSchemaTokens: 0,
|
|
13961
|
+
// already included in the calibrated full-input estimate
|
|
13962
|
+
protocolReserveTokens: 0,
|
|
13963
|
+
output: boundedOutput
|
|
13964
|
+
});
|
|
13965
|
+
}
|
|
13966
|
+
function updateLocalRequestCalibration(previous, actual, estimated) {
|
|
13967
|
+
return Number.isFinite(actual) && actual > 0 && Number.isFinite(estimated) && estimated > 0 ? Math.max(1, actual / estimated) : previous;
|
|
13968
|
+
}
|
|
13899
13969
|
|
|
13900
13970
|
// packages/agent-runtime/toolArgsTruncationPolicy.ts
|
|
13901
13971
|
import { createHash } from "node:crypto";
|
|
@@ -14736,12 +14806,13 @@ function detectExecShellSynchronousWarnings(command, shell) {
|
|
|
14736
14806
|
}
|
|
14737
14807
|
|
|
14738
14808
|
// packages/agent-runtime/capabilities/execShellCapability.ts
|
|
14809
|
+
var WINDOWS_SHELL_NOTE = process.platform === "win32" ? ` On Windows the runtime prefers pwsh (PowerShell 7+): it is resolved first (PATH, then the WindowsApps alias), and powershell.exe 5.1 is only a fallback when pwsh is absent. Read metadata.shellKind from the result \u2014 "pwsh" supports '&&'/'||' and $PSStyle, "powershell5" does not (join with ';' or split calls). Match the syntax to the kind you actually got; never assume the version.` : "";
|
|
14739
14810
|
function buildExecShellToolDefinition(toolName = "execShell") {
|
|
14740
14811
|
return {
|
|
14741
14812
|
type: "function",
|
|
14742
14813
|
function: {
|
|
14743
14814
|
name: toolName,
|
|
14744
|
-
description: `Execute a shell command from the workspace root. Prefer one compound command (e.g. 'git status && git diff --stat') to perform complete verification in one step instead of multiple small roundtrips. Do not cd into guessed paths; commands already run from the workspace root. Commands block until exit. Long-running commands (sleep over ${IMMEDIATE_DETACH_SLEEP_THRESHOLD_SECONDS}s, dev servers, watchers) automatically detach to background returning {detached: true, pid, label}; for persistent services, prefer launchProcess
|
|
14815
|
+
description: `Execute a shell command from the workspace root. Prefer one compound command (e.g. 'git status && git diff --stat') to perform complete verification in one step instead of multiple small roundtrips. Do not cd into guessed paths; commands already run from the workspace root. Commands block until exit. Long-running commands (sleep over ${IMMEDIATE_DETACH_SLEEP_THRESHOLD_SECONDS}s, dev servers, watchers) automatically detach to background returning {detached: true, pid, label}; for persistent services, prefer launchProcess.${WINDOWS_SHELL_NOTE} LIFECYCLE CONTRACT: (1) A normal command waits synchronously for at most 120 seconds; if it ends inside that window the call IS finished \u2014 a result carrying exitCode means the command has already completed: parse it immediately, never read it as "still running" (no later event will remind you). (2) Only a result with metadata.detached === true AND a taskId can deliver an automatic completion turn; that taskId is an opaque handle, NOT a file path and NOT a result file \u2014 never search for, guess or readFile a path from it, and never rerun the command just to obtain its output. That terminal turn delivers the result inline as a bounded capsule; when the capsule was truncated it also carries a real full-output path in its overflow marker \u2014 read that actual path with readFile only when it is present. While waiting for that terminal notification, continue independent work on other parts of the task. A launchProcess taskId is a tracked task too, but it only yields a notice on your next real turn. (3) Text the command itself prints (LAUNCHED, STARTED, ...) is plain stdout with zero lifecycle meaning \u2014 never read it as a platform receipt. (4) Shell-level backgrounding (&, nohup, disown, setsid, self-daemonizing scripts, PowerShell Start-Process) is NOT tracked: those descendants produce no completion notification, and the outer shell finishing tells you nothing about them. Use background: true to turn a finite job into a tracked background task. Do not run standalone sleep commands purely to pause execution. When a synchronous result's core output was redirected to a file, read that file in the SAME turn ("read it later" means it is lost) \u2014 never end the turn promising a later automatic report without a taskId.`,
|
|
14745
14816
|
parameters: {
|
|
14746
14817
|
type: "object",
|
|
14747
14818
|
properties: {
|
|
@@ -14759,7 +14830,7 @@ function buildExecShellToolDefinition(toolName = "execShell") {
|
|
|
14759
14830
|
},
|
|
14760
14831
|
label: {
|
|
14761
14832
|
type: "string",
|
|
14762
|
-
description: "Optional human-readable label for the resulting background task, shown in
|
|
14833
|
+
description: "Optional human-readable label for the resulting background task, shown in task lists and completion notices. Defaults to the last token."
|
|
14763
14834
|
}
|
|
14764
14835
|
}
|
|
14765
14836
|
}
|
|
@@ -15317,6 +15388,52 @@ import { homedir } from "node:os";
|
|
|
15317
15388
|
import { dirname as dirname2, relative as relative4, resolve as resolve4, sep as sep2 } from "node:path";
|
|
15318
15389
|
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
15319
15390
|
|
|
15391
|
+
// packages/agent-runtime/runResultReadProjection.ts
|
|
15392
|
+
import { basename } from "node:path";
|
|
15393
|
+
function projectRunResultRead(path, content, raw = false) {
|
|
15394
|
+
const unchanged = { content, projected: false };
|
|
15395
|
+
if (raw || !basename(path).endsWith(".result.md") || !content.startsWith("---\n")) return unchanged;
|
|
15396
|
+
const end3 = content.indexOf("\n---\n", 4);
|
|
15397
|
+
if (end3 < 0) return unchanged;
|
|
15398
|
+
const header = content.slice(0, end3).split("\n");
|
|
15399
|
+
const runLine = header.find((line) => line.startsWith("runId: "));
|
|
15400
|
+
const index = header.findIndex((line) => line.startsWith("acceptance: "));
|
|
15401
|
+
if (!runLine || index < 0) return unchanged;
|
|
15402
|
+
try {
|
|
15403
|
+
const runId = JSON.parse(runLine.slice(7));
|
|
15404
|
+
if (typeof runId !== "string" || basename(path) !== `${runId}.result.md`) return unchanged;
|
|
15405
|
+
const encoded = JSON.parse(header[index].slice(12));
|
|
15406
|
+
if (typeof encoded !== "string") return unchanged;
|
|
15407
|
+
const acceptance = JSON.parse(encoded);
|
|
15408
|
+
if (!isRecord(acceptance) || acceptance.schemaVersion !== 1 || acceptance.source !== "local-runtime" || !isRecord(acceptance.checks) || !Array.isArray(acceptance.checks.observations)) return unchanged;
|
|
15409
|
+
const { observations, ...checks } = acceptance.checks;
|
|
15410
|
+
let exitZero = 0;
|
|
15411
|
+
let exitNonzero = 0;
|
|
15412
|
+
let exitUnknown = 0;
|
|
15413
|
+
for (const observation of observations) {
|
|
15414
|
+
const code = isRecord(observation) ? observation.exitCode : void 0;
|
|
15415
|
+
if (code === 0) exitZero++;
|
|
15416
|
+
else if (typeof code === "number" && Number.isInteger(code)) exitNonzero++;
|
|
15417
|
+
else exitUnknown++;
|
|
15418
|
+
}
|
|
15419
|
+
const projected = { ...acceptance, checks: { ...checks, observationSummary: {
|
|
15420
|
+
count: observations.length,
|
|
15421
|
+
exitZero,
|
|
15422
|
+
exitNonzero,
|
|
15423
|
+
exitUnknown,
|
|
15424
|
+
evidence: "#/acceptance/checks/observations",
|
|
15425
|
+
readOriginal: "readFile with raw:true (force:true if already read)",
|
|
15426
|
+
limitation: "Exit counts are observations, not version-bound test or review approval."
|
|
15427
|
+
} } };
|
|
15428
|
+
const line = `acceptance: ${JSON.stringify(JSON.stringify(projected))}`;
|
|
15429
|
+
if (line.length >= header[index].length) return unchanged;
|
|
15430
|
+
header[index] = line;
|
|
15431
|
+
return { content: header.join("\n") + content.slice(end3), projected: true };
|
|
15432
|
+
} catch {
|
|
15433
|
+
return unchanged;
|
|
15434
|
+
}
|
|
15435
|
+
}
|
|
15436
|
+
|
|
15320
15437
|
// packages/core/readRangeLedger.ts
|
|
15321
15438
|
function filterRetainedLedgerRecords(records, retainedCap) {
|
|
15322
15439
|
return records.filter((record2) => record2.chars <= retainedCap);
|
|
@@ -15351,15 +15468,27 @@ function isLineRangeCovered(request3, covered) {
|
|
|
15351
15468
|
|
|
15352
15469
|
// packages/agent-runtime/fileTextSearch.ts
|
|
15353
15470
|
import { readdir, readFile as readFile3, stat as stat3 } from "node:fs/promises";
|
|
15354
|
-
import { basename, relative as relative2, resolve as resolve2 } from "node:path";
|
|
15471
|
+
import { basename as basename2, relative as relative2, resolve as resolve2 } from "node:path";
|
|
15355
15472
|
import { spawn as spawnChildProcess } from "node:child_process";
|
|
15356
15473
|
|
|
15357
15474
|
// packages/agent-runtime/gitignore.ts
|
|
15358
15475
|
import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
15359
15476
|
import { resolve } from "node:path";
|
|
15477
|
+
function isIgnorableFsError(err) {
|
|
15478
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
15479
|
+
const code = err.code;
|
|
15480
|
+
return code === "ENOENT" || code === "ENOTDIR";
|
|
15481
|
+
}
|
|
15482
|
+
return false;
|
|
15483
|
+
}
|
|
15360
15484
|
async function readRootGitignorePatterns(workspaceRoot) {
|
|
15361
|
-
|
|
15362
|
-
|
|
15485
|
+
let content;
|
|
15486
|
+
try {
|
|
15487
|
+
content = await readFile2(resolve(workspaceRoot, ".gitignore"), "utf8");
|
|
15488
|
+
} catch (err) {
|
|
15489
|
+
if (isIgnorableFsError(err)) return [];
|
|
15490
|
+
throw err;
|
|
15491
|
+
}
|
|
15363
15492
|
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && !line.startsWith("!")).flatMap((line) => {
|
|
15364
15493
|
const unanchored = line.replace(/^\//, "");
|
|
15365
15494
|
if (unanchored.endsWith("/")) return [`${unanchored}**`];
|
|
@@ -15371,14 +15500,15 @@ async function hasRootGitignore(workspaceRoot) {
|
|
|
15371
15500
|
try {
|
|
15372
15501
|
await stat2(resolve(workspaceRoot, ".gitignore"));
|
|
15373
15502
|
return true;
|
|
15374
|
-
} catch {
|
|
15375
|
-
return false;
|
|
15503
|
+
} catch (err) {
|
|
15504
|
+
if (isIgnorableFsError(err)) return false;
|
|
15505
|
+
throw err;
|
|
15376
15506
|
}
|
|
15377
15507
|
}
|
|
15378
15508
|
|
|
15379
15509
|
// packages/agent-runtime/fileTextSearch.ts
|
|
15380
15510
|
var normalizePath = (value) => value.replaceAll("\\", "/");
|
|
15381
|
-
var pathFor = (root, file, absolute = false) => absolute ? normalizePath(file) : normalizePath(relative2(root, file) ||
|
|
15511
|
+
var pathFor = (root, file, absolute = false) => absolute ? normalizePath(file) : normalizePath(relative2(root, file) || basename2(file));
|
|
15382
15512
|
var COMMAND_LIMIT_HEADROOM = 1;
|
|
15383
15513
|
async function runCommand(binary, args2, cwd, maxResults) {
|
|
15384
15514
|
const recordLimit = maxResults === void 0 ? 0 : Math.max(0, maxResults) + COMMAND_LIMIT_HEADROOM;
|
|
@@ -15404,6 +15534,17 @@ async function runCommand(binary, args2, cwd, maxResults) {
|
|
|
15404
15534
|
}
|
|
15405
15535
|
});
|
|
15406
15536
|
}
|
|
15537
|
+
function extractGrepExcludeDir(pattern) {
|
|
15538
|
+
const p = pattern.replaceAll("\\", "/");
|
|
15539
|
+
if (!p) return null;
|
|
15540
|
+
if (!/\/(\*{1,2})?$/.test(p)) return null;
|
|
15541
|
+
const clean = p.replace(/\/(\*{1,2})?$/, "");
|
|
15542
|
+
if (!clean || clean.includes("/") || /[*?{}[\]]/.test(clean)) return null;
|
|
15543
|
+
return clean;
|
|
15544
|
+
}
|
|
15545
|
+
function isGrepExpressibleExclude(pattern) {
|
|
15546
|
+
return extractGrepExcludeDir(pattern) !== null;
|
|
15547
|
+
}
|
|
15407
15548
|
function commandArgs(o, binary, target) {
|
|
15408
15549
|
const args2 = binary === "rg" ? ["--line-number", "--no-heading", "--color", "never", "--null"] : ["-RIn", "--binary-files=without-match", "--null"];
|
|
15409
15550
|
if (binary === "rg") args2.push("--no-require-git");
|
|
@@ -15416,8 +15557,8 @@ function commandArgs(o, binary, target) {
|
|
|
15416
15557
|
if (o.include) args2.push("--glob", o.include);
|
|
15417
15558
|
} else {
|
|
15418
15559
|
for (const x of o.exclude ?? []) {
|
|
15419
|
-
const clean = x
|
|
15420
|
-
if (clean
|
|
15560
|
+
const clean = extractGrepExcludeDir(x);
|
|
15561
|
+
if (clean) args2.push("--exclude-dir", clean);
|
|
15421
15562
|
}
|
|
15422
15563
|
if (o.include) args2.push("--include", o.include);
|
|
15423
15564
|
}
|
|
@@ -15465,7 +15606,7 @@ function globMatch(pattern, value) {
|
|
|
15465
15606
|
else source += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
15466
15607
|
}
|
|
15467
15608
|
const r = new RegExp(`^${source}$`);
|
|
15468
|
-
return r.test(value) || r.test(
|
|
15609
|
+
return r.test(value) || r.test(basename2(value));
|
|
15469
15610
|
}
|
|
15470
15611
|
var defaultReadTextFile = (filePath) => readFile3(filePath, "utf8").catch(() => "");
|
|
15471
15612
|
async function jsSearch(o, targetPath) {
|
|
@@ -15513,6 +15654,23 @@ async function jsSearch(o, targetPath) {
|
|
|
15513
15654
|
}
|
|
15514
15655
|
return { matches: out, totalMatches: out.length, truncated: false, engine: "js" };
|
|
15515
15656
|
}
|
|
15657
|
+
async function canGrepFulfillOptions(o) {
|
|
15658
|
+
if (!o.includeIgnored) {
|
|
15659
|
+
const gitignorePatterns = await readRootGitignorePatterns(o.root);
|
|
15660
|
+
if (gitignorePatterns.length > 0) return false;
|
|
15661
|
+
}
|
|
15662
|
+
if (o.include) {
|
|
15663
|
+
if (o.include.includes("/") || o.include.includes("\\") || o.include.includes("**") || /[{}[\]]/.test(o.include)) {
|
|
15664
|
+
return false;
|
|
15665
|
+
}
|
|
15666
|
+
}
|
|
15667
|
+
if (o.exclude && o.exclude.length > 0) {
|
|
15668
|
+
for (const pattern of o.exclude) {
|
|
15669
|
+
if (!isGrepExpressibleExclude(pattern)) return false;
|
|
15670
|
+
}
|
|
15671
|
+
}
|
|
15672
|
+
return true;
|
|
15673
|
+
}
|
|
15516
15674
|
var COMMAND_ENGINES = [
|
|
15517
15675
|
{ engine: "ripgrep", binaryOption: "resolveRipgrepBinary", binaryName: "rg", argsKey: "rg" },
|
|
15518
15676
|
{ engine: "grep", binaryOption: "resolveGrepBinary", binaryName: "grep", argsKey: "grep" }
|
|
@@ -15524,6 +15682,7 @@ async function searchFileTextMatches(o) {
|
|
|
15524
15682
|
if (targetStat.isFile()) return jsSearch(o, targetPath);
|
|
15525
15683
|
const run2 = o.runCommand ?? runCommand, max4 = o.maxResults;
|
|
15526
15684
|
for (const entry of COMMAND_ENGINES) {
|
|
15685
|
+
if (entry.engine === "grep" && !await canGrepFulfillOptions(o)) continue;
|
|
15527
15686
|
const injectedResolver = o[entry.binaryOption];
|
|
15528
15687
|
const binary = injectedResolver ? injectedResolver() : resolveExecutableOnPath(entry.binaryName);
|
|
15529
15688
|
if (!binary) continue;
|
|
@@ -15708,13 +15867,15 @@ function runTaskLogs(args2) {
|
|
|
15708
15867
|
const allEvents = registry.getTaskEvents(taskId, 0);
|
|
15709
15868
|
const terminal = lastTerminalEvent(allEvents);
|
|
15710
15869
|
const status = terminal ? reportedTaskStatus(terminal.type, terminal.exitCode) : record2 ? statusOf(record2) : "running";
|
|
15870
|
+
const hint = events.length === 0 && !isProcessTaskTerminalStatus(status) ? `no new events since cursor ${cursor}; the task is still running and there is nothing more to read right now. Don't re-read the same cursor immediately: later events are returned once they exist. Where the host reports completions, wait for that signal; otherwise use taskWait with an explicit budget.` : void 0;
|
|
15711
15871
|
return {
|
|
15712
15872
|
outcome: "ok",
|
|
15713
15873
|
taskId,
|
|
15714
15874
|
cursor: registry.latestTaskSeq(taskId),
|
|
15715
15875
|
events,
|
|
15716
15876
|
status,
|
|
15717
|
-
terminal: isProcessTaskTerminalStatus(status)
|
|
15877
|
+
terminal: isProcessTaskTerminalStatus(status),
|
|
15878
|
+
...hint ? { hint } : {}
|
|
15718
15879
|
};
|
|
15719
15880
|
}
|
|
15720
15881
|
function formatTaskLogsContent(result4, options) {
|
|
@@ -15876,7 +16037,11 @@ function buildReadWorkspaceParameters() {
|
|
|
15876
16037
|
properties: {
|
|
15877
16038
|
path,
|
|
15878
16039
|
lines,
|
|
15879
|
-
force
|
|
16040
|
+
force,
|
|
16041
|
+
raw: {
|
|
16042
|
+
type: "boolean",
|
|
16043
|
+
description: "Read original bytes including full runtime acceptance observations in *.result.md. Default compacts only machine observations; report text and physical line numbers are unchanged."
|
|
16044
|
+
}
|
|
15880
16045
|
},
|
|
15881
16046
|
required: ["path"]
|
|
15882
16047
|
};
|
|
@@ -16201,7 +16366,7 @@ function filterDeclaredWorkspaceToolNames(args2) {
|
|
|
16201
16366
|
// packages/agent-runtime/workspacePathGuard.ts
|
|
16202
16367
|
import { constants as fsConstants } from "node:fs";
|
|
16203
16368
|
import { lstat, mkdir, open, readlink, realpath as realpath2 } from "node:fs/promises";
|
|
16204
|
-
import { basename as
|
|
16369
|
+
import { basename as basename3, dirname, isAbsolute as isAbsolute2, join as join2, relative as relative3, resolve as resolve3, sep } from "node:path";
|
|
16205
16370
|
function isPathInsideRoot(root, targetPath) {
|
|
16206
16371
|
const rel = relative3(resolve3(root), resolve3(targetPath));
|
|
16207
16372
|
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute2(rel);
|
|
@@ -16224,7 +16389,7 @@ async function realpathAllowMissing(targetPath) {
|
|
|
16224
16389
|
if (!isNotFoundError(error)) return null;
|
|
16225
16390
|
const parent = dirname(current);
|
|
16226
16391
|
if (parent === current) return null;
|
|
16227
|
-
tail.push(
|
|
16392
|
+
tail.push(basename3(current));
|
|
16228
16393
|
current = parent;
|
|
16229
16394
|
}
|
|
16230
16395
|
}
|
|
@@ -16418,7 +16583,7 @@ async function createMissingDirectoryChain(guard) {
|
|
|
16418
16583
|
}
|
|
16419
16584
|
try {
|
|
16420
16585
|
for (const target of missing.slice().reverse()) {
|
|
16421
|
-
const name =
|
|
16586
|
+
const name = basename3(target);
|
|
16422
16587
|
if (!name || name === "." || name === "..") {
|
|
16423
16588
|
throw workspacePathGuardError({
|
|
16424
16589
|
ok: false,
|
|
@@ -16662,6 +16827,9 @@ function describeRejectedArgValue(value) {
|
|
|
16662
16827
|
if (Array.isArray(value)) return "an array";
|
|
16663
16828
|
return `a value of type ${typeof value}`;
|
|
16664
16829
|
}
|
|
16830
|
+
function clipMarkerValue(text2, max4 = 60) {
|
|
16831
|
+
return text2.length <= max4 ? text2 : `${text2.slice(0, max4)}\u2026(${text2.length} chars)`;
|
|
16832
|
+
}
|
|
16665
16833
|
function readIntegerArg(args2) {
|
|
16666
16834
|
if (isAbsentArg(args2.value)) return {};
|
|
16667
16835
|
const min4 = args2.min ?? 1;
|
|
@@ -16720,16 +16888,16 @@ function parseLinesArg(value) {
|
|
|
16720
16888
|
}
|
|
16721
16889
|
function readFileSliceArgs(args2) {
|
|
16722
16890
|
const warnings = [];
|
|
16723
|
-
const withFallback = (slice2) => {
|
|
16891
|
+
const withFallback = (slice2, invalidLines) => {
|
|
16724
16892
|
warnings.push(
|
|
16725
16893
|
`No usable line range remained; returned the first ${READ_FILE_SLICE_FALLBACK_LINES} lines instead of the whole file.`
|
|
16726
16894
|
);
|
|
16727
|
-
return { ...slice2, maxLines: READ_FILE_SLICE_FALLBACK_LINES, warnings };
|
|
16895
|
+
return { ...slice2, maxLines: READ_FILE_SLICE_FALLBACK_LINES, warnings, invalidLines };
|
|
16728
16896
|
};
|
|
16729
|
-
if (isAbsentArg(args2.lines)) return { warnings };
|
|
16897
|
+
if (isAbsentArg(args2.lines)) return { warnings, invalidLines: void 0 };
|
|
16730
16898
|
const { slice, warning } = parseLinesArg(args2.lines);
|
|
16731
16899
|
if (warning) warnings.push(warning);
|
|
16732
|
-
return slice ? { ...slice, warnings } : withFallback({});
|
|
16900
|
+
return slice ? { ...slice, warnings, invalidLines: void 0 } : withFallback({}, describeRejectedArgValue(args2.lines));
|
|
16733
16901
|
}
|
|
16734
16902
|
function buildReadFileSliceHint(totalLines) {
|
|
16735
16903
|
return `File has ${totalLines} lines. Use lines: ${LINES_ARG_SYNTAX}, or omit it for the whole file.`;
|
|
@@ -16998,7 +17166,7 @@ var READ_FILE_LEDGER_MAX_KEYS = 256;
|
|
|
16998
17166
|
async function readFileTool(args2) {
|
|
16999
17167
|
const parsed = parseWorkspaceToolArguments(args2.call.arguments);
|
|
17000
17168
|
const requestedPath = requireWorkspaceToolPath(parsed);
|
|
17001
|
-
const { warnings, ...sliceArgs } = readFileSliceArgs(parsed);
|
|
17169
|
+
const { warnings, invalidLines, ...sliceArgs } = readFileSliceArgs(parsed);
|
|
17002
17170
|
const approval = await resolveLocalWorkspaceToolApproval({
|
|
17003
17171
|
workspaceRoot: args2.workspaceRoot,
|
|
17004
17172
|
requestedPath,
|
|
@@ -17006,7 +17174,9 @@ async function readFileTool(args2) {
|
|
|
17006
17174
|
...args2.confirmExternalFileAccess ? { confirmExternalFileAccess: args2.confirmExternalFileAccess } : {}
|
|
17007
17175
|
});
|
|
17008
17176
|
const absolutePath = approval.path;
|
|
17009
|
-
const
|
|
17177
|
+
const originalContent = await readGuardApprovedFile(approval);
|
|
17178
|
+
const projection = projectRunResultRead(absolutePath, originalContent, parsed.raw === true);
|
|
17179
|
+
const content = projection.content;
|
|
17010
17180
|
const activity = extractActivity(parsed);
|
|
17011
17181
|
const sliced = sliceReadFileContent({
|
|
17012
17182
|
content,
|
|
@@ -17016,7 +17186,16 @@ async function readFileTool(args2) {
|
|
|
17016
17186
|
content: sliced.content,
|
|
17017
17187
|
totalLines: sliced.totalLines
|
|
17018
17188
|
});
|
|
17019
|
-
const
|
|
17189
|
+
const invalidLinesMarker = invalidLines !== void 0 ? `[readFile] lines=${clipMarkerValue(invalidLines)} was rejected (only ONE range: ${LINES_ARG_SYNTAX}); returned lines ${sliced.startLine}-${sliced.endLine} instead. Fix the argument before relying on this window.
|
|
17190
|
+
` : "";
|
|
17191
|
+
const finalRead = invalidLinesMarker.length > 0 ? defensivelyTruncateReadFile({
|
|
17192
|
+
content: truncatedRead.content,
|
|
17193
|
+
totalLines: sliced.totalLines,
|
|
17194
|
+
limit: Math.max(1, READ_FILE_MAX_CHAR_LIMIT - invalidLinesMarker.length)
|
|
17195
|
+
}) : truncatedRead;
|
|
17196
|
+
const finalContent = invalidLinesMarker + finalRead.content;
|
|
17197
|
+
const truncatedByCharLimit = truncatedRead.truncatedByCharLimit || finalRead.truncatedByCharLimit;
|
|
17198
|
+
const isTruncated = sliced.truncated || truncatedByCharLimit;
|
|
17020
17199
|
const relativePath = normalizeWorkspaceRelativePath({
|
|
17021
17200
|
workspaceRoot: resolve4(args2.workspaceRoot),
|
|
17022
17201
|
targetPath: absolutePath
|
|
@@ -17024,7 +17203,7 @@ async function readFileTool(args2) {
|
|
|
17024
17203
|
const force = parsed.force === true;
|
|
17025
17204
|
const ledger = args2.readLedger;
|
|
17026
17205
|
const requestRange = { startLine: sliced.startLine, endLine: sliced.endLine };
|
|
17027
|
-
const fingerprint = createHash3("sha1").update(
|
|
17206
|
+
const fingerprint = createHash3("sha1").update(originalContent).update(parsed.raw === true ? "\0raw" : "\0default").digest("hex").slice(0, 20);
|
|
17028
17207
|
let entry = ledger?.get(relativePath);
|
|
17029
17208
|
if (entry && entry.fingerprint !== fingerprint) {
|
|
17030
17209
|
entry = void 0;
|
|
@@ -17052,20 +17231,25 @@ async function readFileTool(args2) {
|
|
|
17052
17231
|
}
|
|
17053
17232
|
const metadata = {
|
|
17054
17233
|
path: relativePath,
|
|
17055
|
-
bytes: Buffer.byteLength(
|
|
17056
|
-
totalBytes: Buffer.byteLength(
|
|
17234
|
+
bytes: Buffer.byteLength(finalContent),
|
|
17235
|
+
totalBytes: Buffer.byteLength(originalContent),
|
|
17236
|
+
...projection.projected ? {
|
|
17237
|
+
projection: "run-result-observations",
|
|
17238
|
+
projectedTotalBytes: Buffer.byteLength(content),
|
|
17239
|
+
rawReadHint: "readFile raw:true reads original evidence; line numbers are unchanged."
|
|
17240
|
+
} : {},
|
|
17057
17241
|
startLine: sliced.startLine,
|
|
17058
17242
|
endLine: sliced.endLine,
|
|
17059
17243
|
totalLines: sliced.totalLines,
|
|
17060
17244
|
truncated: isTruncated,
|
|
17061
|
-
...
|
|
17245
|
+
...truncatedByCharLimit ? { truncatedByByteLimit: true, truncatedByCharLimit: true } : {},
|
|
17062
17246
|
...sliceArgs.maxLines ? { maxLines: sliceArgs.maxLines } : {},
|
|
17063
17247
|
...sliceArgs.tailLines ? { tailLines: sliceArgs.tailLines } : {},
|
|
17064
17248
|
...warnings.length ? { warnings: [...warnings, buildReadFileSliceHint(sliced.totalLines)] } : {},
|
|
17065
17249
|
...activity ? { activity } : {}
|
|
17066
17250
|
};
|
|
17067
17251
|
if (!isTruncated && ledger) {
|
|
17068
|
-
const persistedChars =
|
|
17252
|
+
const persistedChars = finalContent.length + "\n\n[tool metadata]\n".length + JSON.stringify(metadata).length;
|
|
17069
17253
|
const records = entry?.records ?? [];
|
|
17070
17254
|
records.push({ ...requestRange, chars: persistedChars });
|
|
17071
17255
|
ledger.delete(relativePath);
|
|
@@ -17079,7 +17263,7 @@ async function readFileTool(args2) {
|
|
|
17079
17263
|
ledger.delete(oldestKey);
|
|
17080
17264
|
}
|
|
17081
17265
|
}
|
|
17082
|
-
return { content:
|
|
17266
|
+
return { content: finalContent, metadata };
|
|
17083
17267
|
}
|
|
17084
17268
|
async function ensureGuardedParentDirectory(args2) {
|
|
17085
17269
|
const directoryGuard = await resolveWorkspaceSafePath({
|
|
@@ -17978,7 +18162,8 @@ function createLocalWorkspaceToolExecutors(args2) {
|
|
|
17978
18162
|
if (!Array.isArray(paths) || paths.length === 0 || paths.some((path) => typeof path !== "string" || !path.trim())) {
|
|
17979
18163
|
throw new Error("read_image: paths must contain 1 to 4 non-empty string paths (maximum 4 images)");
|
|
17980
18164
|
}
|
|
17981
|
-
const
|
|
18165
|
+
const imagePaths = paths.filter((path) => typeof path === "string");
|
|
18166
|
+
const results2 = await Promise.all(imagePaths.map(async (path) => {
|
|
17982
18167
|
try {
|
|
17983
18168
|
const absolutePath = await resolveLocalWorkspaceToolPath({
|
|
17984
18169
|
workspaceRoot: args2.workspaceRoot,
|
|
@@ -18225,6 +18410,13 @@ function getAgentRuntimeToolParametersIndex() {
|
|
|
18225
18410
|
}
|
|
18226
18411
|
|
|
18227
18412
|
// packages/agent-runtime/localToolPolicy.ts
|
|
18413
|
+
var shellLifecycles = /* @__PURE__ */ new WeakMap();
|
|
18414
|
+
function registerLocalShellLifecycle(executor, lifecycle) {
|
|
18415
|
+
shellLifecycles.set(executor, lifecycle);
|
|
18416
|
+
}
|
|
18417
|
+
function getLocalShellLifecycle(executor) {
|
|
18418
|
+
return executor ? shellLifecycles.get(executor) : void 0;
|
|
18419
|
+
}
|
|
18228
18420
|
var NEVER_LOCAL_TOOLS = /* @__PURE__ */ new Set([
|
|
18229
18421
|
"deleteSpaces",
|
|
18230
18422
|
"updateAgent",
|
|
@@ -18338,12 +18530,13 @@ async function runExecShellGates(args2) {
|
|
|
18338
18530
|
return { kind: "pass", opts };
|
|
18339
18531
|
}
|
|
18340
18532
|
if (args2.execShellApproval) {
|
|
18341
|
-
const
|
|
18533
|
+
const execute = () => invokeCapability("execShell", args2.callArguments, {
|
|
18342
18534
|
...opts,
|
|
18343
18535
|
workspaceRoot: args2.workspaceRoot,
|
|
18344
18536
|
commandOutputLimit: args2.commandOutputLimit,
|
|
18345
18537
|
execShellApproval: args2.execShellApproval
|
|
18346
18538
|
});
|
|
18539
|
+
const result4 = await (args2.shellLifecycle ? args2.shellLifecycle(execute, args2.abortSignal) : execute());
|
|
18347
18540
|
return { kind: "handled", result: result4 };
|
|
18348
18541
|
}
|
|
18349
18542
|
let parsedInput = args2.callArguments;
|
|
@@ -18387,6 +18580,7 @@ async function executeLocalToolWithPolicy(args2) {
|
|
|
18387
18580
|
const gate = await runExecShellGates({
|
|
18388
18581
|
toolName: decision.toolName,
|
|
18389
18582
|
callArguments: args2.call.arguments,
|
|
18583
|
+
shellLifecycle: getLocalShellLifecycle(executor),
|
|
18390
18584
|
execShellApproval: args2.execShellApproval,
|
|
18391
18585
|
workspaceRoot: args2.workspaceRoot,
|
|
18392
18586
|
commandOutputLimit: args2.commandOutputLimit,
|
|
@@ -18407,7 +18601,41 @@ async function executeLocalToolWithPolicy(args2) {
|
|
|
18407
18601
|
);
|
|
18408
18602
|
}
|
|
18409
18603
|
|
|
18604
|
+
// packages/agent-runtime/credentialSinkPolicy.ts
|
|
18605
|
+
var CREDENTIAL_REF_ALLOWED_SINKS = /* @__PURE__ */ new Set();
|
|
18606
|
+
function classifyCredentialRefSink(toolName, allowlist = CREDENTIAL_REF_ALLOWED_SINKS) {
|
|
18607
|
+
if (isCommandExecutingTool(toolName)) return "command";
|
|
18608
|
+
if (allowlist.has(toolName)) return "allow";
|
|
18609
|
+
return "confirm";
|
|
18610
|
+
}
|
|
18611
|
+
function buildCredentialSinkPermissionRequest(toolName) {
|
|
18612
|
+
return {
|
|
18613
|
+
id: `permission-credential-sink-${toolName}`,
|
|
18614
|
+
tool: toolName,
|
|
18615
|
+
action: "credential_unwrap_tool_use",
|
|
18616
|
+
title: "\u786E\u8BA4\u5728\u5DE5\u5177\u53C2\u6570\u4E2D\u4F7F\u7528\u51ED\u636E",
|
|
18617
|
+
body: `\u8BE5\u5DE5\u5177\uFF08${toolName}\uFF09\u7684\u53C2\u6570\u8981\u643A\u5E26\u51ED\u636E\uFF0C\u786E\u8BA4\u540E\u4EC5\u672C\u6B21\u8C03\u7528\u89E3\u5305\uFF1B\u660E\u6587\u4E0D\u4F1A\u5199\u5165\u5386\u53F2\u6216\u8BB0\u5F55\u3002`,
|
|
18618
|
+
suggestedRule: {
|
|
18619
|
+
scope: "once",
|
|
18620
|
+
pattern: { capability: "credential_use", target: "tool_arguments" }
|
|
18621
|
+
}
|
|
18622
|
+
};
|
|
18623
|
+
}
|
|
18624
|
+
|
|
18410
18625
|
// packages/agent-runtime/toolCallTransaction.ts
|
|
18626
|
+
function buildCredentialSinkRefusal(toolName, gateId) {
|
|
18627
|
+
return {
|
|
18628
|
+
content: `\u9700\u8981\u7528\u6237\u786E\u8BA4\u624D\u80FD\u628A\u51ED\u636E\u7528\u4E8E ${toolName}\u3002\u53EF\u6539\u8D70\u53D7\u63A7\u901A\u9053\uFF1Anolo secret run --with <name> -- <cmd>\u3002`,
|
|
18629
|
+
metadata: {
|
|
18630
|
+
cancelled: true,
|
|
18631
|
+
actionGateResult: {
|
|
18632
|
+
status: "cancelled",
|
|
18633
|
+
...gateId ? { gateId } : {}
|
|
18634
|
+
}
|
|
18635
|
+
}
|
|
18636
|
+
};
|
|
18637
|
+
}
|
|
18638
|
+
var credentialGateQueues = /* @__PURE__ */ new WeakMap();
|
|
18411
18639
|
var LOCAL_TURN_ABORTED_CODE = "LOCAL_TURN_ABORTED";
|
|
18412
18640
|
function buildAbortedError() {
|
|
18413
18641
|
const error = new Error("local agent turn aborted by user");
|
|
@@ -18656,32 +18884,72 @@ async function executeToolCall(args2) {
|
|
|
18656
18884
|
const rawArguments = toolCall.function.arguments;
|
|
18657
18885
|
let unwrappedArguments = rawArguments;
|
|
18658
18886
|
if (typeof rawArguments === "string" && rawArguments.includes("$nolo_cred:") && input.adapter.credentialBroker) {
|
|
18659
|
-
|
|
18887
|
+
const sink = classifyCredentialRefSink(toolName);
|
|
18888
|
+
if (sink === "command") {
|
|
18660
18889
|
throw new Error(
|
|
18661
18890
|
`[security] \u62D2\u7EDD\u5728 ${toolName} \u547D\u4EE4\u884C\u4E2D\u76F4\u63A5\u89E3\u5305\u51ED\u8BC1\u5F15\u7528 ($nolo_cred:)\uFF0C\u4EE5\u9632\u5FA1\u63D0\u793A\u8BCD\u6CE8\u5165\u5916\u6CC4\u98CE\u9669\u3002\u8BF7\u4F7F\u7528\u53D7\u63A7\u8BA4\u8BC1\u901A\u9053\u3002`
|
|
18662
18891
|
);
|
|
18663
18892
|
}
|
|
18664
|
-
|
|
18665
|
-
|
|
18666
|
-
|
|
18667
|
-
|
|
18668
|
-
|
|
18669
|
-
|
|
18670
|
-
|
|
18671
|
-
|
|
18672
|
-
|
|
18673
|
-
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
18682
|
-
|
|
18683
|
-
|
|
18684
|
-
|
|
18893
|
+
if (sink === "confirm") {
|
|
18894
|
+
if (input.onActionGate) {
|
|
18895
|
+
const permissionRequest = buildCredentialSinkPermissionRequest(toolName);
|
|
18896
|
+
const gate = {
|
|
18897
|
+
...permissionRequest,
|
|
18898
|
+
// [M1] id 带上 toolCall.id,避免同一轮同一工具两次请求 id 碰撞(对齐既有 ask 分支约定)。
|
|
18899
|
+
id: `${permissionRequest.id}-${toolCall.id}`,
|
|
18900
|
+
kind: "confirm",
|
|
18901
|
+
toolName,
|
|
18902
|
+
toolCallId: toolCall.id
|
|
18903
|
+
};
|
|
18904
|
+
const onActionGate = input.onActionGate;
|
|
18905
|
+
const prev = credentialGateQueues.get(input) ?? Promise.resolve();
|
|
18906
|
+
const next = prev.catch(() => void 0).then(
|
|
18907
|
+
() => runAbortableToolTask(
|
|
18908
|
+
input,
|
|
18909
|
+
onActionGate(gate),
|
|
18910
|
+
`${toolName} credential confirmation`
|
|
18911
|
+
)
|
|
18912
|
+
);
|
|
18913
|
+
credentialGateQueues.set(input, next);
|
|
18914
|
+
const replacement = await next.finally(() => {
|
|
18915
|
+
if (credentialGateQueues.get(input) === next) {
|
|
18916
|
+
credentialGateQueues.delete(input);
|
|
18917
|
+
}
|
|
18918
|
+
});
|
|
18919
|
+
if (replacement !== void 0 && isCompletedActionGateResult(replacement?.metadata?.actionGateResult)) {
|
|
18920
|
+
unwrappedArguments = await unwrapToolArguments(rawArguments, input.adapter.credentialBroker);
|
|
18921
|
+
} else {
|
|
18922
|
+
toolResult = buildCredentialSinkRefusal(toolName, gate.id);
|
|
18923
|
+
}
|
|
18924
|
+
} else {
|
|
18925
|
+
toolResult = buildCredentialSinkRefusal(toolName);
|
|
18926
|
+
}
|
|
18927
|
+
}
|
|
18928
|
+
if (sink === "allow") {
|
|
18929
|
+
unwrappedArguments = await unwrapToolArguments(rawArguments, input.adapter.credentialBroker);
|
|
18930
|
+
}
|
|
18931
|
+
}
|
|
18932
|
+
if (!toolResult) {
|
|
18933
|
+
const executePromise = input.adapter.executeTool({
|
|
18934
|
+
id: toolCall.id,
|
|
18935
|
+
name: toolName,
|
|
18936
|
+
arguments: unwrappedArguments,
|
|
18937
|
+
...userInputText ? { userInput: userInputText } : {},
|
|
18938
|
+
...input.runtimeContext ? { runtimeContext: input.runtimeContext } : {},
|
|
18939
|
+
...args2.runToolNames ? { runToolNames: args2.runToolNames } : {},
|
|
18940
|
+
...input.abortSignal ? { abortSignal: input.abortSignal } : {},
|
|
18941
|
+
// 定档信号:来源只由 turn 输入推导,不让模型/参数层参与。
|
|
18942
|
+
// 三级判据见 plan §10——后台运行优先于子 run(后台派发的子 run 仍是
|
|
18943
|
+
// 无人值守的,按 automation 报更保守)。
|
|
18944
|
+
origin: input.background ? "automation" : input.runKind === "subtask" ? "agent" : "chat"
|
|
18945
|
+
}, {
|
|
18946
|
+
...input.abortSignal ? { abortSignal: input.abortSignal } : {},
|
|
18947
|
+
...input.runtimeContext ? { runtimeContext: input.runtimeContext } : {}
|
|
18948
|
+
});
|
|
18949
|
+
const execStartedAtMs = Date.now();
|
|
18950
|
+
toolResult = await runAbortableToolTask(input, executePromise, toolName);
|
|
18951
|
+
toolExecMs = Date.now() - execStartedAtMs;
|
|
18952
|
+
}
|
|
18685
18953
|
}
|
|
18686
18954
|
if (tailDropNotice) {
|
|
18687
18955
|
toolResult = {
|
|
@@ -18696,6 +18964,15 @@ ${toolResult.content}` : toolResult.content,
|
|
|
18696
18964
|
toolCallId: toolCall.id,
|
|
18697
18965
|
metadata: toolResult.metadata
|
|
18698
18966
|
});
|
|
18967
|
+
if (actionGate && !input.onActionGate && actionGate.kind === "input") {
|
|
18968
|
+
toolResult = {
|
|
18969
|
+
content: "\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u6CA1\u6709\u4EA4\u4E92\u8F93\u5165\u9762\u677F\uFF0C\u65E0\u6CD5\u5F39\u51FA\u51ED\u636E\u586B\u5199\u754C\u9762\uFF0C\u8BE5\u8BF7\u6C42\u5DF2\u88AB\u53D6\u6D88\u3002\u8BF7\u8BA9\u7528\u6237\u5728\u684C\u9762\u7AEF\u6216 Web \u7AEF\u754C\u9762\u63D0\u4F9B\u51ED\u636E\uFF0C\u6216\u76F4\u63A5\u5728\u5BF9\u8BDD\u4E2D\u53D1\u9001\u51ED\u636E\u5185\u5BB9\uFF1B\u51ED\u636E\u4FDD\u5B58\u540E\u7528 nolo secret run --with <NAME> -- <cmd> \u6D88\u8D39\u3002",
|
|
18970
|
+
metadata: {
|
|
18971
|
+
cancelled: true,
|
|
18972
|
+
actionGateResult: { gateId: actionGate.id, status: "cancelled" }
|
|
18973
|
+
}
|
|
18974
|
+
};
|
|
18975
|
+
}
|
|
18699
18976
|
if (actionGate && input.onActionGate) {
|
|
18700
18977
|
const replacement = await runAbortableToolTask(input, input.onActionGate(actionGate), `${toolName} action gate`);
|
|
18701
18978
|
if (replacement) {
|
|
@@ -18789,10 +19066,15 @@ function applyPersistedTurnInput(messages, persistedInput, persistedInputReferen
|
|
|
18789
19066
|
}
|
|
18790
19067
|
function createTurnTranscript(args2) {
|
|
18791
19068
|
let working = args2.initialWorking;
|
|
18792
|
-
|
|
19069
|
+
let raw = args2.initialWorking.slice(
|
|
18793
19070
|
args2.prefixCount + args2.historyCount
|
|
18794
19071
|
);
|
|
18795
19072
|
const cap = args2.capToolMessage ?? ((msg) => msg);
|
|
19073
|
+
function retract(callback4) {
|
|
19074
|
+
const predicate = callback4;
|
|
19075
|
+
working = working.filter((msg) => !predicate(msg));
|
|
19076
|
+
raw = raw.filter((msg) => !predicate(msg));
|
|
19077
|
+
}
|
|
18796
19078
|
return {
|
|
18797
19079
|
working: () => working,
|
|
18798
19080
|
replaceWorkingHistory: (nextWorkingView) => {
|
|
@@ -18811,7 +19093,13 @@ function createTurnTranscript(args2) {
|
|
|
18811
19093
|
raw.pop();
|
|
18812
19094
|
return working.pop();
|
|
18813
19095
|
},
|
|
18814
|
-
|
|
19096
|
+
retract,
|
|
19097
|
+
persisted: (persistedInput, persistedInputReference) => {
|
|
19098
|
+
const firstUser = raw.find(
|
|
19099
|
+
(message) => message.role === "user"
|
|
19100
|
+
);
|
|
19101
|
+
return firstUser?.cliMessageId ? raw.map(withoutToolImages) : applyPersistedTurnInput(raw.map(withoutToolImages), persistedInput, persistedInputReference);
|
|
19102
|
+
}
|
|
18815
19103
|
};
|
|
18816
19104
|
}
|
|
18817
19105
|
|
|
@@ -18863,10 +19151,10 @@ function createTurnUsageLedger(args2) {
|
|
|
18863
19151
|
recordProviderCall: ({ usage, model, provider, telemetry }) => {
|
|
18864
19152
|
turnUsage = mergeTurnUsage(turnUsage, usage);
|
|
18865
19153
|
lastContextUsage = usage;
|
|
18866
|
-
if (usage && Object.keys(usage).length > 0) {
|
|
19154
|
+
if (usage && Object.keys(usage).length > 0 || telemetry?.requestState) {
|
|
18867
19155
|
providerRecords.push({
|
|
18868
|
-
callId: resolveRecordCallId(usage),
|
|
18869
|
-
usage,
|
|
19156
|
+
callId: resolveRecordCallId(usage ?? {}),
|
|
19157
|
+
usage: usage ?? {},
|
|
18870
19158
|
model: model || args2.model || "unknown",
|
|
18871
19159
|
...provider || args2.provider ? { provider: provider || args2.provider } : {},
|
|
18872
19160
|
...telemetry && Object.keys(telemetry).length > 0 ? { telemetry } : {},
|
|
@@ -18897,7 +19185,42 @@ function createTurnUsageLedger(args2) {
|
|
|
18897
19185
|
}
|
|
18898
19186
|
|
|
18899
19187
|
// packages/agent-runtime/leafFinalHandoff.ts
|
|
18900
|
-
var LEAF_FINAL_HANDOFF_INSTRUCTIONS = `Leaf subtask final: return only the result, blockers/findings, and minimal evidence the parent needs. Do not narrate your process or restate the task. Keep success minimal (a one-line result is enough); on failure include the blocker, severity when relevant, and an evidence reference (file:line, test command, commit, artifact, or run/dialog). If the task explicitly requires a long-form deliverable (document, translation, dataset, code, or other artifact), provide that deliverable in full and keep only the handoff around it concise. During execution, follow the brief as given: report only results incremental to the brief, new evidence, overturned assumptions, and remaining questions; only when new evidence would materially change the goal, risk, irreversibility, or DoD should you surface it as a blocker/finding \u2014 do not silently expand scope or re-litigate the settled direction.
|
|
19188
|
+
var LEAF_FINAL_HANDOFF_INSTRUCTIONS = `Leaf subtask final: return only the result, blockers/findings, and minimal evidence the parent needs. Do not narrate your process or restate the task. Keep success minimal (a one-line result is enough); on failure include the blocker, severity when relevant, and an evidence reference (file:line, test command, commit, artifact, or run/dialog). If the task explicitly requires a long-form deliverable (document, translation, dataset, code, or other artifact), provide that deliverable in full and keep only the handoff around it concise. During execution, follow the brief as given: report only results incremental to the brief, new evidence, overturned assumptions, and remaining questions; only when new evidence would materially change the goal, risk, irreversibility, or DoD should you surface it as a blocker/finding \u2014 do not silently expand scope or re-litigate the settled direction. Own investigation, implementation, related checks and failure fixes within the brief\u2019s scope and budget; leave goals and critical decisions to the parent. For required DoD checks, include the worktree, checked version (including uncommitted change scope), command, check scope, pass/fail and original-output reference; explicitly mark checks not run or evidence unavailable. Reuse valid same-version evidence; additional checks are warranted for version changes, missing/conflicting evidence or integration risk. Do not invent version metadata or treat a completion summary as independent review approval. Keep success concise without omitting required evidence.`;
|
|
19189
|
+
|
|
19190
|
+
// packages/agent-runtime/taskExecutionContract.ts
|
|
19191
|
+
var present = (value) => typeof value === "string" && value.trim().length > 0;
|
|
19192
|
+
function evaluateTaskExecutionContract(contract, outcome = {}) {
|
|
19193
|
+
if (!contract) return void 0;
|
|
19194
|
+
const result4 = (status, ...reasons) => ({ taskId: contract.taskId, status, reasons });
|
|
19195
|
+
if (outcome.stopped) return result4("blocked", "stopped");
|
|
19196
|
+
if (!present(contract.taskId) || !["owner", "implementation-leaf"].includes(contract.role) || !["active", "paused", "revoked"].includes(contract.authorization) || !["pending", "waived", "accepted", "unknown"].includes(contract.acceptance) || !["complete", "incomplete", "unknown"].includes(contract.implementation) || !["changed", "unchanged", "unknown"].includes(contract.changes)) {
|
|
19197
|
+
return result4("blocked", "invalid_contract");
|
|
19198
|
+
}
|
|
19199
|
+
if (contract.authorization === "revoked") return result4("blocked", "authorization_revoked");
|
|
19200
|
+
if (contract.authorization === "paused") return result4("blocked", "authorization_paused");
|
|
19201
|
+
if (outcome.executionFailed) return result4("blocked", "execution_failed");
|
|
19202
|
+
if (outcome.budgetExhausted) return result4("incomplete", "budget_exhausted");
|
|
19203
|
+
if (contract.implementation !== "complete") return result4("incomplete", "implementation_incomplete");
|
|
19204
|
+
if (contract.acceptance === "pending") return result4("waiting", "acceptance_pending");
|
|
19205
|
+
if (contract.acceptance === "unknown") return result4("blocked", "acceptance_unknown");
|
|
19206
|
+
if (contract.changes === "unknown") return result4("incomplete", "changes_unknown");
|
|
19207
|
+
if (contract.role === "implementation-leaf" || contract.changes === "unchanged") return result4("completed");
|
|
19208
|
+
if (!present(contract.revision)) return result4("incomplete", "revision_missing");
|
|
19209
|
+
const review = contract.review;
|
|
19210
|
+
if (!review || !present(review.evidenceRef)) return result4("incomplete", "review_missing");
|
|
19211
|
+
if (review.revision !== contract.revision) return result4("incomplete", "review_stale");
|
|
19212
|
+
if (!present(contract.authorInstanceId) || !present(review.reviewerInstanceId) || review.reviewerInstanceId === contract.authorInstanceId) return result4("blocked", "review_not_independent");
|
|
19213
|
+
if (review.verdict !== "APPROVE" || review.hasCriticalOrHigh !== false) return result4("blocked", "review_rejected");
|
|
19214
|
+
const commit = contract.commit;
|
|
19215
|
+
if (!commit || !present(commit.commitId) || !present(commit.evidenceRef)) return result4("incomplete", "commit_missing");
|
|
19216
|
+
if (commit.revision !== contract.revision) return result4("incomplete", "commit_stale");
|
|
19217
|
+
const merge4 = contract.localMerge;
|
|
19218
|
+
if (!merge4 || !present(merge4.targetBranch) || !present(merge4.mergeCommitId) || !present(merge4.evidenceRef)) {
|
|
19219
|
+
return result4("incomplete", "local_merge_missing");
|
|
19220
|
+
}
|
|
19221
|
+
if (merge4.sourceCommitId !== commit.commitId) return result4("incomplete", "local_merge_mismatch");
|
|
19222
|
+
return result4("completed");
|
|
19223
|
+
}
|
|
18901
19224
|
|
|
18902
19225
|
// packages/agent-runtime/contextBlockScope.ts
|
|
18903
19226
|
var isContextBlockScope = (value) => {
|
|
@@ -18913,6 +19236,34 @@ var normalizeContextBlockScopes = (legacyBlocks = void 0, scopes = void 0) => {
|
|
|
18913
19236
|
return (Array.isArray(legacyBlocks) ? legacyBlocks : []).filter((block) => typeof block === "string").map((block) => block.trim()).filter((block) => block.length > 0).map((block) => ({ content: block, cacheScope: "turn" }));
|
|
18914
19237
|
};
|
|
18915
19238
|
|
|
19239
|
+
// packages/agent-runtime/providerInputItemLimits.ts
|
|
19240
|
+
var PROVIDER_INPUT_ITEM_LIMITS = [
|
|
19241
|
+
{
|
|
19242
|
+
provider: "opendesign",
|
|
19243
|
+
endpointHost: "open-design.ai",
|
|
19244
|
+
// Upstream HTTP 400: "[code=context_length_exceeded] Input is too long:
|
|
19245
|
+
// conversation history exceeds the limit on input items (1003 > 1000 items)."
|
|
19246
|
+
// type=invalid_request_error, code=context_length_exceeded, param=messages.
|
|
19247
|
+
maxInputItems: 1e3
|
|
19248
|
+
}
|
|
19249
|
+
];
|
|
19250
|
+
function resolveProviderInputItemLimit(args2) {
|
|
19251
|
+
const byProvider = PROVIDER_INPUT_ITEM_LIMITS.find(
|
|
19252
|
+
(entry) => entry.provider === args2.provider?.toLowerCase()
|
|
19253
|
+
);
|
|
19254
|
+
if (byProvider) return byProvider.maxInputItems;
|
|
19255
|
+
if (!args2.endpoint) return void 0;
|
|
19256
|
+
let host;
|
|
19257
|
+
try {
|
|
19258
|
+
host = new URL(args2.endpoint.includes("://") ? args2.endpoint : `https://${args2.endpoint}`).hostname.toLowerCase();
|
|
19259
|
+
} catch {
|
|
19260
|
+
return void 0;
|
|
19261
|
+
}
|
|
19262
|
+
return PROVIDER_INPUT_ITEM_LIMITS.find(
|
|
19263
|
+
(entry) => host === entry.endpointHost || host.endsWith(`.${entry.endpointHost}`)
|
|
19264
|
+
)?.maxInputItems;
|
|
19265
|
+
}
|
|
19266
|
+
|
|
18916
19267
|
// packages/agent-runtime/localAutoCompaction.ts
|
|
18917
19268
|
import { randomUUID } from "node:crypto";
|
|
18918
19269
|
function toPlanCompressionMessages(history) {
|
|
@@ -18991,25 +19342,75 @@ function projectHistoryWithSummary(args2) {
|
|
|
18991
19342
|
return [...summaryMsg, ...preservedUser, ...projected];
|
|
18992
19343
|
}
|
|
18993
19344
|
var COLD_RESUME_IDLE_MS = 60 * 60 * 1e3;
|
|
18994
|
-
async function
|
|
19345
|
+
async function completeRoutedCompactionSummary(args2) {
|
|
19346
|
+
const budget = createSummaryBudget({ mode: "automatic", signal: args2.options.signal, deadlineMs: args2.options.deadlineMs });
|
|
18995
19347
|
try {
|
|
18996
|
-
const
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
stage: "fallback"
|
|
19348
|
+
const options = { ...args2.options, signal: budget.signal, deadlineMs: budget.deadlineMs };
|
|
19349
|
+
const eligible = await budget.run(async () => {
|
|
19350
|
+
try {
|
|
19351
|
+
return await args2.fallback.preferPlatform?.(options) === true;
|
|
19352
|
+
} catch (error) {
|
|
19353
|
+
if (budget.signal.aborted || isAbortError(error) || error?.name === "TimeoutError") throw error;
|
|
19354
|
+
return false;
|
|
19355
|
+
}
|
|
19005
19356
|
});
|
|
19006
|
-
|
|
19007
|
-
|
|
19357
|
+
let currentResult;
|
|
19358
|
+
const result4 = await runSummaryWithContract({
|
|
19359
|
+
budget,
|
|
19360
|
+
eligibility: { userId: "authenticated-account", authenticated: eligible, platformAvailable: eligible, credits: eligible ? 1 : void 0 },
|
|
19361
|
+
platform: {
|
|
19362
|
+
model: PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL,
|
|
19363
|
+
provider: "nolo",
|
|
19364
|
+
attemptId: options.attemptId,
|
|
19365
|
+
run: async () => args2.fallback.complete ? args2.fallback.complete(args2.content, options) : { text: await args2.fallback(args2.content, options) ?? "" }
|
|
19366
|
+
},
|
|
19367
|
+
current: { attemptId: options.attemptId, run: async () => {
|
|
19368
|
+
currentResult = await args2.current();
|
|
19369
|
+
return {
|
|
19370
|
+
text: currentResult.content ?? "",
|
|
19371
|
+
finishReason: currentResult.finish_reason,
|
|
19372
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
19373
|
+
completionTokens: summaryCompletionTokens(currentResult.usage)
|
|
19374
|
+
};
|
|
19375
|
+
} }
|
|
19376
|
+
});
|
|
19377
|
+
if (result4.kind === "error" || result4.kind === "cancelled") {
|
|
19378
|
+
throw Object.assign(new Error(result4.error.message), result4.error, {
|
|
19379
|
+
type: result4.error.errorType,
|
|
19380
|
+
name: result4.kind === "cancelled" ? "AbortError" : result4.error.category === "timeout" ? "TimeoutError" : "SummaryError"
|
|
19381
|
+
});
|
|
19382
|
+
}
|
|
19383
|
+
if (result4.kind === "truncated") throw {
|
|
19384
|
+
code: "SUMMARY_TRUNCATED",
|
|
19385
|
+
stage: "decode",
|
|
19386
|
+
finishReason: result4.completion?.finishReason,
|
|
19387
|
+
maxOutputTokens: result4.completion?.maxOutputTokens ?? options.maxOutputTokens,
|
|
19388
|
+
completionTokens: result4.completion?.completionTokens,
|
|
19389
|
+
outputChars: result4.completion?.text.length,
|
|
19390
|
+
responseStatus: result4.completion?.responseStatus,
|
|
19391
|
+
incompleteReason: result4.completion?.incompleteReason,
|
|
19392
|
+
model: result4.route === "platform" ? PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL : currentResult?.model,
|
|
19393
|
+
provider: result4.route === "platform" ? "nolo" : currentResult?.provider
|
|
19394
|
+
};
|
|
19395
|
+
return result4.route === "current" && currentResult ? { ...currentResult, summaryCompletion: result4.completion } : {
|
|
19396
|
+
content: result4.kind === "success" ? result4.text : "",
|
|
19397
|
+
model: PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL,
|
|
19398
|
+
provider: "nolo",
|
|
19399
|
+
summaryCompletion: result4.completion
|
|
19400
|
+
};
|
|
19401
|
+
} finally {
|
|
19402
|
+
budget.dispose();
|
|
19008
19403
|
}
|
|
19009
19404
|
}
|
|
19010
19405
|
var COMPACTION_RETRY_BACKOFF_MS = 6e4;
|
|
19011
19406
|
var COMPACTION_RETRY_BACKOFF_MAX_ENTRIES = 256;
|
|
19012
19407
|
var compactionRetryBackoff = /* @__PURE__ */ new Map();
|
|
19408
|
+
var COMPACTION_RETRY_DELAYS_MS = [3e3, 8e3];
|
|
19409
|
+
var compactionRetryDelaysOverride;
|
|
19410
|
+
function compactionRetryDelayMs(retryCount) {
|
|
19411
|
+
const table = compactionRetryDelaysOverride ?? COMPACTION_RETRY_DELAYS_MS;
|
|
19412
|
+
return table[Math.min(retryCount, table.length - 1)];
|
|
19413
|
+
}
|
|
19013
19414
|
function isCompactionBackedOff(dialogId, now) {
|
|
19014
19415
|
for (const [key, until2] of compactionRetryBackoff) {
|
|
19015
19416
|
if (until2 <= now) compactionRetryBackoff.delete(key);
|
|
@@ -19079,7 +19480,19 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19079
19480
|
reason = "hash-mismatch";
|
|
19080
19481
|
}
|
|
19081
19482
|
console.warn(
|
|
19082
|
-
`[localLoop] invalidated dialog summary for ${dialogId} (${reason}); discarding and re-compressing
|
|
19483
|
+
`[localLoop] invalidated dialog summary for ${dialogId} (${reason}); discarding and re-compressing`,
|
|
19484
|
+
// 诊断分项(**仅加日志,不改任何哈希/校验/重锚语义**):区分「历史真被改写」
|
|
19485
|
+
// 与「保存/重算口径不一致」。只记长度、条数、消息 id 与哈希前 8 位;
|
|
19486
|
+
// 消息正文与摘要正文一律不进日志。重算哈希只发生在失效分支内,
|
|
19487
|
+
// 健康路径零额外开销。
|
|
19488
|
+
{
|
|
19489
|
+
reason,
|
|
19490
|
+
historyLength: history.length,
|
|
19491
|
+
storedSourceCount: typeof invalidStored?.sourceCount === "number" ? invalidStored.sourceCount : null,
|
|
19492
|
+
summarizedBeforeId: typeof invalidStored?.summarizedBeforeId === "string" ? invalidStored.summarizedBeforeId : null,
|
|
19493
|
+
recomputedHashPrefix: hashSummarySourceSlice(history, invalidStored?.summarizedBeforeId)?.slice(0, 8) ?? null,
|
|
19494
|
+
storedHashPrefix: typeof invalidStored?.sourceHash === "string" && invalidStored.sourceHash ? invalidStored.sourceHash.slice(0, 8) : null
|
|
19495
|
+
}
|
|
19083
19496
|
);
|
|
19084
19497
|
stored = null;
|
|
19085
19498
|
}
|
|
@@ -19088,18 +19501,34 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19088
19501
|
const legacyAnchorIndex = summarizedBeforeId ? findSummaryAnchorIndex(bridged, summarizedBeforeId) : -1;
|
|
19089
19502
|
const planAnchorId = summarizedBeforeId && /^local-(0|[1-9]\d*)$/.test(summarizedBeforeId) && legacyAnchorIndex >= 0 ? bridged[legacyAnchorIndex].id : summarizedBeforeId;
|
|
19090
19503
|
const contextWindow = typeof args2.contextWindow === "number" && Number.isFinite(args2.contextWindow) && args2.contextWindow > 0 ? args2.contextWindow : getModelContextWindow(args2.model ?? "");
|
|
19091
|
-
const allMsgs = toPlanCompressionMessages(history);
|
|
19504
|
+
const allMsgs = toPlanCompressionMessages(prepareHistoryForNextTurn(history, args2.contextReferenceResolver));
|
|
19505
|
+
const maxInputItems = resolveProviderInputItemLimit({ provider: args2.provider, endpoint: args2.providerEndpoint });
|
|
19506
|
+
const force = args2.force === true || args2.requestOverBudget?.(
|
|
19507
|
+
existingSummary ? projectHistoryWithSummary({ history, summary: existingSummary, summarizedBeforeId }) : history
|
|
19508
|
+
) === true;
|
|
19092
19509
|
const plan = planCompression({
|
|
19093
19510
|
allMsgs,
|
|
19094
19511
|
summarizedBeforeId: planAnchorId,
|
|
19095
19512
|
summary: existingSummary,
|
|
19096
19513
|
contextWindow,
|
|
19514
|
+
// 失败路径补救:预算裁剪即将丢消息时由 localLoop 传入 force,交由 planCompression
|
|
19515
|
+
// 的既有 force 语义产出待压缩切片(仍受最小条数/安全前缀约束)。
|
|
19516
|
+
force,
|
|
19517
|
+
...force ? { reason: "budget_rescue" } : {},
|
|
19518
|
+
availableHistoryTokens: args2.availableHistoryTokens,
|
|
19097
19519
|
preserveLatestUserByProjection: true,
|
|
19520
|
+
maxInputItems,
|
|
19098
19521
|
...args2.realContextUsagePercent !== void 0 ? { realContextUsagePercent: args2.realContextUsagePercent } : {}
|
|
19099
19522
|
});
|
|
19523
|
+
const itemDiagnostics = maxInputItems !== void 0 ? {
|
|
19524
|
+
itemCount: plan.diagnostics?.itemCount,
|
|
19525
|
+
maxInputItems,
|
|
19526
|
+
triggeredByItemLimit: plan.diagnostics?.triggeredByItemLimit
|
|
19527
|
+
} : {};
|
|
19100
19528
|
const projectExisting = () => {
|
|
19101
19529
|
const diag = plan.diagnostics;
|
|
19102
19530
|
const diagSnapshot = diag ? {
|
|
19531
|
+
...itemDiagnostics,
|
|
19103
19532
|
estimatedTokens: diag.totalUsed,
|
|
19104
19533
|
historyBudget: diag.historyBudget,
|
|
19105
19534
|
triggerRatio: diag.triggerRatio,
|
|
@@ -19107,7 +19536,7 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19107
19536
|
} : {};
|
|
19108
19537
|
const skippedDecision = {
|
|
19109
19538
|
outcome: "skipped",
|
|
19110
|
-
skipReason: diag?.emptyReason === "no-pending" ? "no-pending" : diag?.emptyReason === "below-min-compress-count" ? "below-min-compress-count" : "below-trigger",
|
|
19539
|
+
skipReason: diag?.emptyReason === "no-pending" ? "no-pending" : diag?.emptyReason === "below-min-compress-count" ? "below-min-compress-count" : diag?.emptyReason === "no-safe-prefix" ? "no-safe-prefix" : "below-trigger",
|
|
19111
19540
|
...diagSnapshot,
|
|
19112
19541
|
...diag ? { pendingMsgCount: diag.pendingMsgCount } : {},
|
|
19113
19542
|
...diag?.compressCount !== void 0 ? { compressCount: diag.compressCount } : {}
|
|
@@ -19121,6 +19550,13 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19121
19550
|
}),
|
|
19122
19551
|
compressed: true,
|
|
19123
19552
|
summaryGenerated: false,
|
|
19553
|
+
selectedSummary: {
|
|
19554
|
+
outcome: "loaded",
|
|
19555
|
+
hash: sha256Hex(existingSummary),
|
|
19556
|
+
...summarizedBeforeId ? { anchorId: summarizedBeforeId } : {},
|
|
19557
|
+
...stored?.sourceHash ? { sourceHash: stored.sourceHash } : {},
|
|
19558
|
+
...stored?.sourceCount !== void 0 ? { sourceCount: stored.sourceCount } : {}
|
|
19559
|
+
},
|
|
19124
19560
|
decision: {
|
|
19125
19561
|
outcome: "compressed",
|
|
19126
19562
|
trigger: "existing-summary",
|
|
@@ -19141,6 +19577,7 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19141
19577
|
outcome: "skipped",
|
|
19142
19578
|
skipReason: "retry-backoff",
|
|
19143
19579
|
...diag ? {
|
|
19580
|
+
...itemDiagnostics,
|
|
19144
19581
|
estimatedTokens: diag.totalUsed,
|
|
19145
19582
|
historyBudget: diag.historyBudget,
|
|
19146
19583
|
triggerRatio: diag.triggerRatio,
|
|
@@ -19158,14 +19595,22 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19158
19595
|
});
|
|
19159
19596
|
if (bounded3.status === "blocked") {
|
|
19160
19597
|
const detail = `bounded compaction blocked: ${bounded3.reason}`;
|
|
19161
|
-
console.warn(
|
|
19598
|
+
console.warn(
|
|
19599
|
+
`[localLoop] ${detail}`,
|
|
19600
|
+
...bounded3.diagnostics ? [bounded3.diagnostics] : []
|
|
19601
|
+
);
|
|
19162
19602
|
return {
|
|
19163
19603
|
...projectExisting(),
|
|
19164
19604
|
decision: { outcome: "skipped", skipReason: "bounded-request-blocked", detail }
|
|
19165
19605
|
};
|
|
19166
19606
|
}
|
|
19167
19607
|
emitPhase({ kind: "compaction-start" });
|
|
19168
|
-
|
|
19608
|
+
let compactionAttemptId = randomUUID();
|
|
19609
|
+
const maxAttempts = 3;
|
|
19610
|
+
let attempt = 0;
|
|
19611
|
+
let retryCount = 0;
|
|
19612
|
+
let attemptRoute = "current";
|
|
19613
|
+
let attemptTimingLogged = false;
|
|
19169
19614
|
let compactionT0 = Date.now();
|
|
19170
19615
|
let compactionInputTokens;
|
|
19171
19616
|
let compactionPrevSummaryTokens;
|
|
@@ -19174,7 +19619,15 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19174
19619
|
let primaryElapsedMs;
|
|
19175
19620
|
let fallbackElapsedMs;
|
|
19176
19621
|
let saveElapsedMs;
|
|
19622
|
+
let summaryDeadlineMs = Infinity;
|
|
19623
|
+
let summaryModel = args2.model;
|
|
19624
|
+
let summaryProvider = args2.provider;
|
|
19625
|
+
let summaryDiagnostics = {
|
|
19626
|
+
maxOutputTokens: bounded3.outputTokenBudget
|
|
19627
|
+
};
|
|
19177
19628
|
const logCompactionTiming = (outcome, fields) => {
|
|
19629
|
+
if (attemptTimingLogged) return;
|
|
19630
|
+
attemptTimingLogged = true;
|
|
19178
19631
|
if (compactionInputTokens === void 0 && compactionInputSource !== void 0) {
|
|
19179
19632
|
compactionInputTokens = estimateTokenCount(compactionInputSource);
|
|
19180
19633
|
}
|
|
@@ -19184,10 +19637,20 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19184
19637
|
console.log(
|
|
19185
19638
|
`[compaction-timing] ${JSON.stringify({
|
|
19186
19639
|
attemptId: compactionAttemptId,
|
|
19187
|
-
|
|
19640
|
+
attempt,
|
|
19641
|
+
maxAttempts,
|
|
19642
|
+
physicalAttempts: attempt,
|
|
19643
|
+
route: attemptRoute,
|
|
19644
|
+
model: fields.model ?? summaryModel ?? null,
|
|
19645
|
+
provider: summaryProvider ?? null,
|
|
19188
19646
|
inputTokens: compactionInputTokens ?? null,
|
|
19189
19647
|
prevSummaryTokens: compactionPrevSummaryTokens ?? null,
|
|
19190
|
-
outputChars: fields.outputChars ?? null,
|
|
19648
|
+
outputChars: summaryDiagnostics.outputChars ?? fields.outputChars ?? null,
|
|
19649
|
+
finishReason: summaryDiagnostics.finishReason ?? null,
|
|
19650
|
+
responseStatus: summaryDiagnostics.responseStatus ?? null,
|
|
19651
|
+
incompleteReason: summaryDiagnostics.incompleteReason ?? null,
|
|
19652
|
+
maxOutputTokens: summaryDiagnostics.maxOutputTokens ?? null,
|
|
19653
|
+
completionTokens: summaryDiagnostics.completionTokens ?? null,
|
|
19191
19654
|
elapsedMs: Date.now() - compactionT0,
|
|
19192
19655
|
primaryElapsedMs: primaryElapsedMs ?? null,
|
|
19193
19656
|
fallbackElapsedMs: fallbackElapsedMs ?? null,
|
|
@@ -19197,10 +19660,11 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19197
19660
|
);
|
|
19198
19661
|
};
|
|
19199
19662
|
try {
|
|
19200
|
-
|
|
19201
|
-
|
|
19202
|
-
|
|
19203
|
-
|
|
19663
|
+
let reportAttemptUsage2 = function(value) {
|
|
19664
|
+
const usage = value?.usage;
|
|
19665
|
+
if (usage && typeof usage === "object") args2.onAttemptUsage?.(usage);
|
|
19666
|
+
};
|
|
19667
|
+
var reportAttemptUsage = reportAttemptUsage2;
|
|
19204
19668
|
if (args2.abortSignal?.aborted) {
|
|
19205
19669
|
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
19206
19670
|
}
|
|
@@ -19209,35 +19673,144 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19209
19673
|
compactionInputSource = promptContent;
|
|
19210
19674
|
compactionPrevSummarySource = existingSummary;
|
|
19211
19675
|
compactionT0 = Date.now();
|
|
19212
|
-
const timeoutMs = typeof args2.timeoutMs === "number" && Number.isFinite(args2.timeoutMs) && args2.timeoutMs > 0 ? args2.timeoutMs :
|
|
19676
|
+
const timeoutMs = Math.min(6e4, typeof args2.timeoutMs === "number" && Number.isFinite(args2.timeoutMs) && args2.timeoutMs > 0 ? args2.timeoutMs : 6e4);
|
|
19677
|
+
const requestDeadlineMs = Date.now() + timeoutMs;
|
|
19678
|
+
summaryDeadlineMs = requestDeadlineMs;
|
|
19213
19679
|
const requestController = new AbortController();
|
|
19214
19680
|
let timeoutHandle;
|
|
19215
19681
|
let abortListener;
|
|
19216
19682
|
if (args2.abortSignal?.aborted) requestController.abort(args2.abortSignal.reason);
|
|
19217
|
-
|
|
19218
|
-
|
|
19219
|
-
{
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
|
|
19229
|
-
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
|
|
19238
|
-
|
|
19239
|
-
|
|
19240
|
-
|
|
19683
|
+
let currentOnly = false;
|
|
19684
|
+
const physicalRequest = async (route, operation) => {
|
|
19685
|
+
if (attempt >= maxAttempts) throw { code: "SUMMARY_ATTEMPT_LIMIT" };
|
|
19686
|
+
if (requestController.signal.aborted) throw requestController.signal.reason;
|
|
19687
|
+
attempt++;
|
|
19688
|
+
attemptRoute = route;
|
|
19689
|
+
attemptTimingLogged = false;
|
|
19690
|
+
compactionAttemptId = randomUUID();
|
|
19691
|
+
compactionT0 = Date.now();
|
|
19692
|
+
primaryElapsedMs = void 0;
|
|
19693
|
+
summaryDiagnostics = { maxOutputTokens: bounded3.outputTokenBudget };
|
|
19694
|
+
try {
|
|
19695
|
+
const value = await operation();
|
|
19696
|
+
reportAttemptUsage2(value);
|
|
19697
|
+
return value;
|
|
19698
|
+
} catch (error) {
|
|
19699
|
+
reportAttemptUsage2(error);
|
|
19700
|
+
const safe = classifySummaryError(error);
|
|
19701
|
+
summaryDiagnostics = {
|
|
19702
|
+
...summaryDiagnostics,
|
|
19703
|
+
finishReason: safe.finishReason,
|
|
19704
|
+
responseStatus: safe.responseStatus,
|
|
19705
|
+
incompleteReason: safe.incompleteReason,
|
|
19706
|
+
completionTokens: safe.completionTokens,
|
|
19707
|
+
outputChars: safe.outputChars,
|
|
19708
|
+
maxOutputTokens: safe.maxOutputTokens ?? bounded3.outputTokenBudget
|
|
19709
|
+
};
|
|
19710
|
+
primaryElapsedMs = Date.now() - compactionT0;
|
|
19711
|
+
logCompactionTiming(safe.category === "cancelled" ? "aborted" : safe.category === "timeout" ? "timeout" : "provider-error", {});
|
|
19712
|
+
throw error;
|
|
19713
|
+
}
|
|
19714
|
+
};
|
|
19715
|
+
const currentRequest = async () => {
|
|
19716
|
+
currentOnly = true;
|
|
19717
|
+
const provider = await args2.resolveProvider();
|
|
19718
|
+
summaryModel = provider.model ?? args2.model;
|
|
19719
|
+
summaryProvider = args2.provider;
|
|
19720
|
+
if (requestController.signal.aborted) throw requestController.signal.reason ?? new DOMException("Summary cancelled", "AbortError");
|
|
19721
|
+
try {
|
|
19722
|
+
return await physicalRequest("current", () => provider.complete(
|
|
19723
|
+
[{ role: "system", content: COMPACTION_SUMMARY_SYSTEM_PROMPT }, { role: "user", content: promptContent }],
|
|
19724
|
+
{
|
|
19725
|
+
signal: requestController.signal,
|
|
19726
|
+
timeoutMs: Math.max(1, requestDeadlineMs - Date.now()),
|
|
19727
|
+
// 仅日志用的 attempt id:让 compaction 埋点与 transport 诊断日志 /
|
|
19728
|
+
// 服务端 x-request-id 可对上,用于关联请求级证据。不进 prompt/摘要/持久化。
|
|
19729
|
+
requestId: compactionAttemptId,
|
|
19730
|
+
// Room for factual handoff, exact commands and file operations.
|
|
19731
|
+
max_tokens: bounded3.outputTokenBudget,
|
|
19732
|
+
reasoning_effort: "low"
|
|
19733
|
+
}
|
|
19734
|
+
));
|
|
19735
|
+
} catch (cause) {
|
|
19736
|
+
const safe = classifySummaryError(cause, { model: provider.model, provider: args2.provider ?? void 0, attemptId: compactionAttemptId });
|
|
19737
|
+
throw Object.assign(new Error(safe.message), safe, {
|
|
19738
|
+
type: safe.errorType,
|
|
19739
|
+
name: safe.category === "cancelled" ? "AbortError" : safe.category === "timeout" ? "TimeoutError" : "SummaryError"
|
|
19740
|
+
});
|
|
19741
|
+
}
|
|
19742
|
+
};
|
|
19743
|
+
const fallback = args2.summaryFallback?.preferPlatform ? args2.summaryFallback : void 0;
|
|
19744
|
+
let eligibility;
|
|
19745
|
+
const routedFallback = fallback ? Object.assign(
|
|
19746
|
+
async (content, options) => {
|
|
19747
|
+
summaryModel = PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL;
|
|
19748
|
+
summaryProvider = "nolo";
|
|
19749
|
+
return physicalRequest("platform", () => fallback(content, { ...options, attemptId: compactionAttemptId }));
|
|
19750
|
+
},
|
|
19751
|
+
{
|
|
19752
|
+
preferPlatform: (options) => eligibility ??= fallback.preferPlatform(options),
|
|
19753
|
+
...fallback.complete ? { complete: async (content, options) => {
|
|
19754
|
+
summaryModel = PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL;
|
|
19755
|
+
summaryProvider = "nolo";
|
|
19756
|
+
return physicalRequest("platform", () => fallback.complete(content, { ...options, attemptId: compactionAttemptId }));
|
|
19757
|
+
} } : {}
|
|
19758
|
+
}
|
|
19759
|
+
) : void 0;
|
|
19760
|
+
const requestOnce = () => routedFallback && !currentOnly ? completeRoutedCompactionSummary({
|
|
19761
|
+
fallback: routedFallback,
|
|
19762
|
+
content: promptContent,
|
|
19763
|
+
options: {
|
|
19764
|
+
signal: requestController.signal,
|
|
19765
|
+
deadlineMs: requestDeadlineMs,
|
|
19766
|
+
attemptId: compactionAttemptId,
|
|
19767
|
+
maxOutputTokens: bounded3.outputTokenBudget
|
|
19768
|
+
},
|
|
19769
|
+
current: currentRequest
|
|
19770
|
+
}) : currentRequest();
|
|
19771
|
+
const request3 = (async () => {
|
|
19772
|
+
for (; ; ) {
|
|
19773
|
+
try {
|
|
19774
|
+
return await requestOnce();
|
|
19775
|
+
} catch (error) {
|
|
19776
|
+
const safe = classifySummaryError(error);
|
|
19777
|
+
const terminal = isQuotaExhaustedError(safe.status ?? 0, safe.code, safe.errorType) || safe.category === "cancelled" || safe.category === "timeout" || ["PROVIDER_UNAVAILABLE", "SUMMARY_TRUNCATED", "INSUFFICIENT_BALANCE"].includes(safe.code ?? "") || safe.errorType === "insufficient_balance_error";
|
|
19778
|
+
const busy = !terminal && (safe.category === "http" && (safe.status === 503 || safe.status === 429) || /^(capacity|overload(?:ed)?|rate[_-]?limit(?:ed)?)(?:[_-](?:error|exceeded))?$/i.test(safe.errorType ?? "") || ["PLATFORM_LLM_BUSY", "RATE_LIMIT", "CAPACITY", "OVERLOAD", "RESOURCE_EXHAUSTED"].includes(safe.code ?? ""));
|
|
19779
|
+
const delayMs = compactionRetryDelayMs(retryCount);
|
|
19780
|
+
if (!busy || attempt >= maxAttempts || requestController.signal.aborted || requestDeadlineMs - Date.now() < delayMs + 5e3) throw error;
|
|
19781
|
+
primaryElapsedMs = Date.now() - compactionT0;
|
|
19782
|
+
logCompactionTiming("provider-error", {});
|
|
19783
|
+
emitPhase({ kind: "compaction-retry", attempt: attempt + 1, maxAttempts });
|
|
19784
|
+
await new Promise((resolve6, reject) => {
|
|
19785
|
+
const signal = requestController.signal;
|
|
19786
|
+
const cancel = () => {
|
|
19787
|
+
clearTimeout(timer);
|
|
19788
|
+
signal.removeEventListener("abort", cancel);
|
|
19789
|
+
reject(signal.reason);
|
|
19790
|
+
};
|
|
19791
|
+
const timer = setTimeout(() => {
|
|
19792
|
+
signal.removeEventListener("abort", cancel);
|
|
19793
|
+
resolve6();
|
|
19794
|
+
}, delayMs);
|
|
19795
|
+
signal.addEventListener("abort", cancel, { once: true });
|
|
19796
|
+
if (signal.aborted) cancel();
|
|
19797
|
+
});
|
|
19798
|
+
if (requestController.signal.aborted || requestDeadlineMs - Date.now() < 5e3) throw error;
|
|
19799
|
+
retryCount++;
|
|
19800
|
+
}
|
|
19801
|
+
}
|
|
19802
|
+
})().then(
|
|
19803
|
+
(value) => ({ kind: "done", value }),
|
|
19804
|
+
(error) => ({ kind: "provider-error", error })
|
|
19805
|
+
);
|
|
19806
|
+
const guards = [];
|
|
19807
|
+
if (timeoutMs) guards.push(new Promise((resolve6) => {
|
|
19808
|
+
timeoutHandle = setTimeout(() => {
|
|
19809
|
+
requestController.abort(new DOMException("Summary deadline exceeded", "TimeoutError"));
|
|
19810
|
+
resolve6({ kind: "timeout" });
|
|
19811
|
+
}, timeoutMs);
|
|
19812
|
+
}));
|
|
19813
|
+
if (args2.abortSignal) guards.push(new Promise((resolve6) => {
|
|
19241
19814
|
abortListener = () => {
|
|
19242
19815
|
requestController.abort(args2.abortSignal?.reason);
|
|
19243
19816
|
resolve6({ kind: "aborted" });
|
|
@@ -19250,71 +19823,37 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19250
19823
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
19251
19824
|
if (abortListener) args2.abortSignal?.removeEventListener("abort", abortListener);
|
|
19252
19825
|
const result4 = outcome.kind === "done" ? outcome.value : void 0;
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
if (
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
compactionReason: "aborted"
|
|
19278
|
-
});
|
|
19279
|
-
}
|
|
19280
|
-
if (fallbackResult.summary) {
|
|
19281
|
-
newSummary = fallbackResult.summary;
|
|
19282
|
-
} else {
|
|
19283
|
-
fallbackFailureDetail = fallbackResult.error ?? "no summary";
|
|
19284
|
-
}
|
|
19826
|
+
if (result4?.model) summaryModel = result4.model;
|
|
19827
|
+
if (result4?.provider) summaryProvider = result4.provider;
|
|
19828
|
+
if (outcome.kind === "aborted") throw Object.assign(new Error("Summary cancelled"), { name: "AbortError", compactionReason: "aborted" });
|
|
19829
|
+
if (outcome.kind === "timeout") throw Object.assign(new Error("Summary deadline exceeded"), { compactionReason: "timeout" });
|
|
19830
|
+
if (outcome.kind === "provider-error") throw outcome.error;
|
|
19831
|
+
const completion = result4?.summaryCompletion;
|
|
19832
|
+
const diagnostic = classifySummaryError({
|
|
19833
|
+
finishReason: completion?.finishReason ?? result4?.finish_reason,
|
|
19834
|
+
responseStatus: completion?.responseStatus,
|
|
19835
|
+
incompleteReason: completion?.incompleteReason,
|
|
19836
|
+
maxOutputTokens: completion?.maxOutputTokens ?? bounded3.outputTokenBudget,
|
|
19837
|
+
completionTokens: completion?.completionTokens ?? summaryCompletionTokens(result4?.usage),
|
|
19838
|
+
outputChars: completion?.text.length ?? result4?.content?.length
|
|
19839
|
+
});
|
|
19840
|
+
summaryDiagnostics = {
|
|
19841
|
+
finishReason: diagnostic.finishReason,
|
|
19842
|
+
responseStatus: diagnostic.responseStatus,
|
|
19843
|
+
incompleteReason: diagnostic.incompleteReason,
|
|
19844
|
+
maxOutputTokens: diagnostic.maxOutputTokens,
|
|
19845
|
+
completionTokens: diagnostic.completionTokens,
|
|
19846
|
+
outputChars: diagnostic.outputChars
|
|
19847
|
+
};
|
|
19848
|
+
if (isTruncatedCompletion({ ...completion, finishReason: completion?.finishReason ?? result4?.finish_reason })) {
|
|
19849
|
+
throw { code: "SUMMARY_TRUNCATED", stage: "decode", ...summaryDiagnostics };
|
|
19285
19850
|
}
|
|
19851
|
+
const newSummary = result4?.content?.trim() ?? "";
|
|
19286
19852
|
if (!newSummary) {
|
|
19287
|
-
|
|
19288
|
-
|
|
19289
|
-
|
|
19290
|
-
|
|
19291
|
-
const fallbackDiagnostic = fallbackElapsedMs !== void 0 ? `; fallback failed (${fallbackElapsedMs}ms): ${fallbackFailureDetail ?? "no summary"}` : "";
|
|
19292
|
-
const combinedDetail = `${primaryDiagnostic}${fallbackDiagnostic}`;
|
|
19293
|
-
if (outcome.kind === "done") {
|
|
19294
|
-
console.warn(
|
|
19295
|
-
"[localLoop] auto-compaction produced empty summary; keeping prior projection"
|
|
19296
|
-
);
|
|
19297
|
-
logCompactionTiming("empty", {});
|
|
19298
|
-
const failureReason = "provider-error";
|
|
19299
|
-
emitPhase({ kind: "compaction-failed", reason: failureReason });
|
|
19300
|
-
const failureMessage = combinedDetail.slice(0, 200);
|
|
19301
|
-
return {
|
|
19302
|
-
...projectExisting(),
|
|
19303
|
-
failureMessage,
|
|
19304
|
-
failureReason,
|
|
19305
|
-
decision: {
|
|
19306
|
-
outcome: "failed",
|
|
19307
|
-
reason: failureReason,
|
|
19308
|
-
detail: failureMessage
|
|
19309
|
-
}
|
|
19310
|
-
};
|
|
19311
|
-
}
|
|
19312
|
-
const reason = primaryFailure ?? "provider-error";
|
|
19313
|
-
throw Object.assign(new Error(combinedDetail), {
|
|
19314
|
-
compactionReason: reason,
|
|
19315
|
-
primaryElapsedMs,
|
|
19316
|
-
fallbackElapsedMs
|
|
19317
|
-
});
|
|
19853
|
+
recordCompactionFailure(dialogId, args2.now?.() ?? Date.now());
|
|
19854
|
+
logCompactionTiming("empty", { model: result4?.model });
|
|
19855
|
+
emitPhase({ kind: "compaction-end" });
|
|
19856
|
+
return { ...projectExisting(), failureMessage: "Summary empty", failureReason: "provider-error", decision: { outcome: "failed", reason: "provider-error", detail: "Summary empty", ...itemDiagnostics } };
|
|
19318
19857
|
}
|
|
19319
19858
|
const metricsReason = invalidSummary ? "invalid_summary" : "context_budget";
|
|
19320
19859
|
const metrics = buildCompactionMetricsFromPlan({
|
|
@@ -19325,36 +19864,51 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19325
19864
|
msgsToKeep: [...msgsToCompress.slice(bounded3.coveredMessages.length), ...plan.msgsToKeep]
|
|
19326
19865
|
},
|
|
19327
19866
|
newSummary,
|
|
19328
|
-
summaryUsage: result4?.usage
|
|
19867
|
+
summaryUsage: result4?.usage,
|
|
19868
|
+
summaryInput: {
|
|
19869
|
+
inputTokens: bounded3.inputTokens,
|
|
19870
|
+
capTokens: bounded3.capTokens,
|
|
19871
|
+
expandedMessages: bounded3.expandedMessages,
|
|
19872
|
+
omittedMessages: bounded3.omittedMessages
|
|
19873
|
+
},
|
|
19874
|
+
planCounts: {
|
|
19875
|
+
pendingMessageCount: plan.diagnostics?.pendingMsgCount,
|
|
19876
|
+
plannedCompressCount: plan.diagnostics?.compressCount
|
|
19877
|
+
}
|
|
19329
19878
|
});
|
|
19330
19879
|
const projectedHistory = projectHistoryWithSummary({
|
|
19331
19880
|
history,
|
|
19332
19881
|
summary: newSummary,
|
|
19333
19882
|
summarizedBeforeId: bounded3.summarizedBeforeId
|
|
19334
19883
|
});
|
|
19335
|
-
const projectedMessages = toPlanCompressionMessages(projectedHistory);
|
|
19884
|
+
const projectedMessages = toPlanCompressionMessages(prepareHistoryForNextTurn(projectedHistory, args2.contextReferenceResolver));
|
|
19336
19885
|
const projectedTokens = projectedMessages.reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0);
|
|
19337
19886
|
const projectedRetained = projectedMessages.slice(1);
|
|
19338
19887
|
metrics.retainedTokens = projectedRetained.reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0);
|
|
19339
19888
|
metrics.retainedCount = projectedRetained.length;
|
|
19340
|
-
const {
|
|
19889
|
+
const { effectiveRawMessageBudget } = resolveEffectiveCompactionBudgets({
|
|
19341
19890
|
contextWindow,
|
|
19342
19891
|
triggerRatio: plan.diagnostics.triggerRatio,
|
|
19343
|
-
historyBudget:
|
|
19344
|
-
rawMessageBudget:
|
|
19345
|
-
summaryTokens: 0
|
|
19892
|
+
historyBudget: contextWindow,
|
|
19893
|
+
rawMessageBudget: contextWindow,
|
|
19894
|
+
summaryTokens: 0,
|
|
19895
|
+
newSummaryTokenReserve: estimateTokenCount(newSummary)
|
|
19346
19896
|
});
|
|
19347
|
-
const
|
|
19897
|
+
const effectiveHistoryBudget = effectiveRawMessageBudget + estimateTokenCount(newSummary);
|
|
19898
|
+
const projectedItemCount = projectedHistory.length + 1;
|
|
19899
|
+
const withinSafetyBudget = projectedTokens <= effectiveHistoryBudget && (maxInputItems === void 0 || projectedItemCount <= Math.floor(maxInputItems * 0.6));
|
|
19348
19900
|
if (!withinSafetyBudget) {
|
|
19349
19901
|
console.warn("[localLoop] compaction projection remains above safety budget", {
|
|
19350
19902
|
projectedTokens,
|
|
19351
|
-
effectiveHistoryBudget
|
|
19903
|
+
effectiveHistoryBudget,
|
|
19904
|
+
...maxInputItems !== void 0 ? { projectedItemCount, maxInputItems } : {}
|
|
19352
19905
|
});
|
|
19353
19906
|
}
|
|
19354
19907
|
const oldProjection = projectExisting();
|
|
19355
|
-
const beforeProjectedTokens = toPlanCompressionMessages(oldProjection.history).reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0);
|
|
19356
|
-
const historyBudget =
|
|
19357
|
-
|
|
19908
|
+
const beforeProjectedTokens = toPlanCompressionMessages(prepareHistoryForNextTurn(oldProjection.history, args2.contextReferenceResolver)).reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0);
|
|
19909
|
+
const historyBudget = Math.max(0, contextWindow - Math.min(8192, Math.max(1, Math.floor(contextWindow / 4))));
|
|
19910
|
+
const candidateOverBudget = args2.requestOverBudget ? args2.requestOverBudget(projectedHistory) : projectedTokens > historyBudget;
|
|
19911
|
+
if (projectedTokens >= beforeProjectedTokens || candidateOverBudget) {
|
|
19358
19912
|
const failureMessage = `compaction candidate rejected: ${projectedTokens >= beforeProjectedTokens ? "no token reduction" : "above history budget"} (before=${beforeProjectedTokens}, after=${projectedTokens}, budget=${historyBudget})`;
|
|
19359
19913
|
console.warn(`[localLoop] ${failureMessage}`);
|
|
19360
19914
|
recordCompactionFailure(dialogId, args2.now?.() ?? Date.now());
|
|
@@ -19364,13 +19918,20 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19364
19918
|
...oldProjection,
|
|
19365
19919
|
failureMessage,
|
|
19366
19920
|
...result4?.usage ? { usage: result4.usage } : {},
|
|
19367
|
-
decision: {
|
|
19921
|
+
decision: {
|
|
19922
|
+
outcome: "skipped",
|
|
19923
|
+
skipReason: "unsafe-projection",
|
|
19924
|
+
detail: failureMessage,
|
|
19925
|
+
...itemDiagnostics,
|
|
19926
|
+
...maxInputItems !== void 0 ? { projectedItemCount } : {}
|
|
19927
|
+
}
|
|
19368
19928
|
};
|
|
19369
19929
|
}
|
|
19370
19930
|
const sourceMeta = await computeSummarySourceMetadata(
|
|
19371
19931
|
toPlanCompressionMessages(history),
|
|
19372
19932
|
bounded3.summarizedBeforeId
|
|
19373
19933
|
);
|
|
19934
|
+
if (Date.now() >= summaryDeadlineMs) throw Object.assign(new Error("Summary deadline exceeded"), { compactionReason: "timeout" });
|
|
19374
19935
|
if (args2.abortSignal?.aborted) {
|
|
19375
19936
|
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
19376
19937
|
}
|
|
@@ -19400,6 +19961,13 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19400
19961
|
history: projectedHistory,
|
|
19401
19962
|
compressed: true,
|
|
19402
19963
|
summaryGenerated: true,
|
|
19964
|
+
selectedSummary: {
|
|
19965
|
+
outcome: "generated",
|
|
19966
|
+
hash: sha256Hex(newSummary),
|
|
19967
|
+
anchorId: bounded3.summarizedBeforeId,
|
|
19968
|
+
...sourceMeta?.sourceHash ? { sourceHash: sourceMeta.sourceHash } : {},
|
|
19969
|
+
...sourceMeta?.sourceCount !== void 0 ? { sourceCount: sourceMeta.sourceCount } : {}
|
|
19970
|
+
},
|
|
19403
19971
|
reason: metricsReason,
|
|
19404
19972
|
beforeTokens: beforeProjectedTokens,
|
|
19405
19973
|
afterTokens: projectedTokens,
|
|
@@ -19408,7 +19976,9 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19408
19976
|
metrics,
|
|
19409
19977
|
decision: {
|
|
19410
19978
|
outcome: "compressed",
|
|
19411
|
-
trigger: invalidSummary ? "invalid-summary" : plan.diagnostics?.triggeredByRealUsage ? "real-usage" : "estimate",
|
|
19979
|
+
trigger: invalidSummary ? "invalid-summary" : plan.diagnostics?.triggeredByItemLimit ? "item-limit" : plan.diagnostics?.triggeredByRealUsage ? "real-usage" : "estimate",
|
|
19980
|
+
...itemDiagnostics,
|
|
19981
|
+
...maxInputItems !== void 0 ? { projectedItemCount } : {},
|
|
19412
19982
|
...plan.diagnostics ? {
|
|
19413
19983
|
estimatedTokens: plan.diagnostics.totalUsed,
|
|
19414
19984
|
historyBudget: plan.diagnostics.historyBudget,
|
|
@@ -19418,18 +19988,39 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19418
19988
|
}
|
|
19419
19989
|
};
|
|
19420
19990
|
} catch (error) {
|
|
19421
|
-
|
|
19422
|
-
|
|
19423
|
-
|
|
19991
|
+
const safe = classifySummaryError(error, { model: summaryModel ?? void 0, provider: summaryProvider ?? void 0, attemptId: compactionAttemptId });
|
|
19992
|
+
summaryModel = safe.model ?? summaryModel;
|
|
19993
|
+
summaryProvider = safe.provider ?? summaryProvider;
|
|
19994
|
+
const failureReason = args2.abortSignal?.aborted || safe.category === "cancelled" || error?.compactionReason === "aborted" ? "aborted" : safe.category === "timeout" || error?.compactionReason === "timeout" ? "timeout" : "provider-error";
|
|
19995
|
+
const failureMessage = [safe.message, safe.code, safe.errorType, safe.balanceSource].filter(Boolean).join(" ");
|
|
19996
|
+
if (failureReason !== "aborted") console.warn("[localLoop] auto-compaction failed:", safe);
|
|
19997
|
+
summaryDiagnostics = {
|
|
19998
|
+
...summaryDiagnostics,
|
|
19999
|
+
...safe.finishReason === void 0 ? {} : { finishReason: safe.finishReason },
|
|
20000
|
+
...safe.responseStatus === void 0 ? {} : { responseStatus: safe.responseStatus },
|
|
20001
|
+
...safe.incompleteReason === void 0 ? {} : { incompleteReason: safe.incompleteReason },
|
|
20002
|
+
...safe.maxOutputTokens === void 0 ? {} : { maxOutputTokens: safe.maxOutputTokens },
|
|
20003
|
+
...safe.completionTokens === void 0 ? {} : { completionTokens: safe.completionTokens },
|
|
20004
|
+
...safe.outputChars === void 0 ? {} : { outputChars: safe.outputChars }
|
|
20005
|
+
};
|
|
19424
20006
|
logCompactionTiming(failureReason, {});
|
|
19425
20007
|
const failureNow = args2.now?.() ?? Date.now();
|
|
19426
20008
|
if (failureReason !== "aborted") recordCompactionFailure(dialogId, failureNow);
|
|
19427
|
-
emitPhase({ kind: "compaction-
|
|
20009
|
+
if (failureReason === "aborted") emitPhase({ kind: "compaction-end" });
|
|
20010
|
+
else emitPhase({ kind: "compaction-failed", reason: failureReason });
|
|
19428
20011
|
return {
|
|
19429
20012
|
...projectExisting(),
|
|
19430
20013
|
failureMessage,
|
|
19431
20014
|
failureReason,
|
|
19432
|
-
|
|
20015
|
+
failure: safe,
|
|
20016
|
+
decision: {
|
|
20017
|
+
outcome: "failed",
|
|
20018
|
+
reason: failureReason,
|
|
20019
|
+
detail: failureMessage,
|
|
20020
|
+
...itemDiagnostics,
|
|
20021
|
+
estimatedTokens: plan.diagnostics?.totalUsed,
|
|
20022
|
+
historyBudget: plan.diagnostics?.historyBudget
|
|
20023
|
+
}
|
|
19433
20024
|
};
|
|
19434
20025
|
}
|
|
19435
20026
|
}
|
|
@@ -19440,13 +20031,14 @@ function emitCompactionPhaseEvent(boundary, phase, scope3) {
|
|
|
19440
20031
|
emitLoopEvent(boundary, { kind: "turn-phase", phase: "compacting", atMs, compactionScope: scope3 });
|
|
19441
20032
|
emitLoopEvent(boundary, { kind: "compaction-start", atMs, scope: scope3 });
|
|
19442
20033
|
} else if (phase.kind === "waiting-provider") emitLoopEvent(boundary, { kind: "turn-phase", phase: "waiting-provider", atMs, compactionScope: scope3 });
|
|
20034
|
+
else if (phase.kind === "compaction-retry") emitLoopEvent(boundary, { kind: "compaction-retry", atMs, scope: scope3, attempt: phase.attempt, maxAttempts: phase.maxAttempts });
|
|
19443
20035
|
else if (phase.kind === "compaction-end") emitLoopEvent(boundary, { kind: "compaction-end", atMs, scope: scope3 });
|
|
19444
20036
|
else emitLoopEvent(boundary, { kind: "compaction-failed", atMs, scope: scope3, reason: phase.reason });
|
|
19445
20037
|
}
|
|
19446
20038
|
function emitCompactionObservationEvent(boundary, compacted) {
|
|
19447
20039
|
const decision = compacted.decision;
|
|
19448
20040
|
if (decision?.outcome === "skipped") {
|
|
19449
|
-
const isProtectionGap = decision.skipReason === "bounded-request-blocked" || decision.skipReason === "unsafe-projection" || decision.skipReason === "adapter-missing-summary-methods" || decision.skipReason === "load-summary-failed";
|
|
20041
|
+
const isProtectionGap = decision.skipReason === "bounded-request-blocked" || decision.skipReason === "unsafe-projection" || decision.skipReason === "no-safe-prefix" || decision.skipReason === "adapter-missing-summary-methods" || decision.skipReason === "load-summary-failed";
|
|
19450
20042
|
const approachingBudget = decision.skipReason === "below-trigger" && typeof decision.estimatedTokens === "number" && typeof decision.historyBudget === "number" && decision.historyBudget > 0 && decision.estimatedTokens >= decision.historyBudget * 0.5;
|
|
19451
20043
|
if (!isProtectionGap && !approachingBudget) return;
|
|
19452
20044
|
}
|
|
@@ -19454,7 +20046,7 @@ function emitCompactionObservationEvent(boundary, compacted) {
|
|
|
19454
20046
|
kind: "compaction",
|
|
19455
20047
|
atMs: Date.now(),
|
|
19456
20048
|
...compacted.reason ? { reason: compacted.reason } : {},
|
|
19457
|
-
...compacted.withinSafetyBudget === false ? { detail: "
|
|
20049
|
+
...compacted.withinSafetyBudget === false ? { detail: "Projected history remains above the token or input-item safety budget" } : {},
|
|
19458
20050
|
summaryGenerated: compacted.summaryGenerated,
|
|
19459
20051
|
compressed: compacted.compressed,
|
|
19460
20052
|
...compacted.failureMessage ? { failed: true, detail: compacted.failureMessage } : {},
|
|
@@ -19464,6 +20056,12 @@ function emitCompactionObservationEvent(boundary, compacted) {
|
|
|
19464
20056
|
...decision && "historyBudget" in decision && decision.historyBudget !== void 0 ? { historyBudget: decision.historyBudget } : {},
|
|
19465
20057
|
...decision && "realUsageRatio" in decision && decision.realUsageRatio !== void 0 ? { realUsageRatio: decision.realUsageRatio } : {},
|
|
19466
20058
|
...decision && "triggerRatio" in decision && decision.triggerRatio !== void 0 ? { triggerRatio: decision.triggerRatio } : {},
|
|
20059
|
+
...decision?.maxInputItems !== void 0 ? {
|
|
20060
|
+
itemCount: decision.itemCount,
|
|
20061
|
+
maxInputItems: decision.maxInputItems,
|
|
20062
|
+
triggeredByItemLimit: decision.triggeredByItemLimit,
|
|
20063
|
+
...decision.projectedItemCount !== void 0 ? { projectedItemCount: decision.projectedItemCount } : {}
|
|
20064
|
+
} : {},
|
|
19467
20065
|
...compacted.beforeTokens !== void 0 ? { beforeTokens: compacted.beforeTokens } : {},
|
|
19468
20066
|
...compacted.afterTokens !== void 0 ? { afterTokens: compacted.afterTokens } : {},
|
|
19469
20067
|
...compacted.savedTokens !== void 0 ? { savedTokens: compacted.savedTokens } : {}
|
|
@@ -19482,7 +20080,7 @@ function createTurnCompactionController(args2) {
|
|
|
19482
20080
|
}
|
|
19483
20081
|
};
|
|
19484
20082
|
const compactionDialogId = args2.continueDialogId ?? ephemeralDialogId;
|
|
19485
|
-
const
|
|
20083
|
+
const runCompaction = async (history, force) => {
|
|
19486
20084
|
let realContextUsagePercent;
|
|
19487
20085
|
if (args2.continueDialogId && typeof args2.adapter.loadLastContextUsage === "function") {
|
|
19488
20086
|
try {
|
|
@@ -19505,15 +20103,21 @@ function createTurnCompactionController(args2) {
|
|
|
19505
20103
|
adapter: args2.adapter,
|
|
19506
20104
|
dialogId: args2.continueDialogId,
|
|
19507
20105
|
history,
|
|
20106
|
+
contextReferenceResolver: args2.contextReferenceResolver,
|
|
19508
20107
|
model: args2.model,
|
|
20108
|
+
provider: args2.provider,
|
|
20109
|
+
providerEndpoint: args2.providerEndpoint,
|
|
19509
20110
|
resolveProvider: args2.resolveProvider,
|
|
19510
20111
|
contextWindow: args2.contextWindow,
|
|
19511
20112
|
realContextUsagePercent,
|
|
20113
|
+
force,
|
|
19512
20114
|
abortSignal: args2.abortSignal,
|
|
19513
20115
|
timeoutMs: args2.timeoutMs,
|
|
19514
20116
|
summaryFallback: args2.summaryFallback,
|
|
20117
|
+
onAttemptUsage: args2.onUsage,
|
|
19515
20118
|
onPhase: (phase) => emitPhase(phase, "initial")
|
|
19516
20119
|
});
|
|
20120
|
+
args2.onSelectedSummary?.(compacted.selectedSummary ?? { outcome: "absent" });
|
|
19517
20121
|
emitObservation(compacted);
|
|
19518
20122
|
return { history: compacted.history, usage: compacted.usage };
|
|
19519
20123
|
} catch (error) {
|
|
@@ -19521,11 +20125,25 @@ function createTurnCompactionController(args2) {
|
|
|
19521
20125
|
return { history };
|
|
19522
20126
|
}
|
|
19523
20127
|
};
|
|
19524
|
-
const
|
|
20128
|
+
const runInitial = async (history) => runCompaction(history, false);
|
|
20129
|
+
const forceCompact = async (history) => {
|
|
20130
|
+
const result4 = await runCompaction(history, true);
|
|
20131
|
+
return { history: result4.history, applied: result4.history !== history, usage: result4.usage };
|
|
20132
|
+
};
|
|
20133
|
+
let lastCompactionOutcome;
|
|
20134
|
+
const prepareRequest = async (requestOverBudget, initial = false, availableHistoryTokens) => {
|
|
20135
|
+
lastCompactionOutcome = void 0;
|
|
19525
20136
|
const contextUsage = args2.getContextUsage();
|
|
19526
|
-
|
|
20137
|
+
let inputTokens = contextUsage ? normalizeUsage(contextUsage).input_tokens : 0;
|
|
20138
|
+
if (initial && args2.continueDialogId && args2.adapter.loadLastContextUsage) {
|
|
20139
|
+
try {
|
|
20140
|
+
inputTokens = (await args2.adapter.loadLastContextUsage(args2.continueDialogId))?.inputTokens ?? 0;
|
|
20141
|
+
} catch (error) {
|
|
20142
|
+
console.warn("[localLoop] loadLastContextUsage failed:", error);
|
|
20143
|
+
}
|
|
20144
|
+
}
|
|
19527
20145
|
const ratio = inputTokens > 0 ? Math.min(1, inputTokens / args2.contextWindow) : void 0;
|
|
19528
|
-
if (ratio !== void 0 && ratio < args2.compressionTriggerRatio * 0.85) {
|
|
20146
|
+
if (!requestOverBudget && ratio !== void 0 && ratio < args2.compressionTriggerRatio * 0.85 && resolveProviderInputItemLimit({ provider: args2.provider, endpoint: args2.providerEndpoint }) === void 0) {
|
|
19529
20147
|
return;
|
|
19530
20148
|
}
|
|
19531
20149
|
try {
|
|
@@ -19538,18 +20156,22 @@ function createTurnCompactionController(args2) {
|
|
|
19538
20156
|
// 锚点与 sourceHash 都必须按持久化形态计算——否则下轮从 store
|
|
19539
20157
|
// 重载后重算 hash 必不匹配,摘要被判无效、白付一次摘要调用。
|
|
19540
20158
|
history: args2.getCanonicalCompactionHistory(),
|
|
20159
|
+
requestOverBudget,
|
|
20160
|
+
availableHistoryTokens: availableHistoryTokens?.(),
|
|
20161
|
+
contextReferenceResolver: args2.contextReferenceResolver,
|
|
19541
20162
|
model: args2.model,
|
|
20163
|
+
provider: args2.provider,
|
|
20164
|
+
providerEndpoint: args2.providerEndpoint,
|
|
19542
20165
|
resolveProvider: args2.resolveProvider,
|
|
19543
20166
|
contextWindow: args2.contextWindow,
|
|
19544
20167
|
...ratio !== void 0 ? { realContextUsagePercent: ratio } : {},
|
|
19545
20168
|
abortSignal: args2.abortSignal,
|
|
19546
20169
|
timeoutMs: args2.timeoutMs,
|
|
19547
20170
|
summaryFallback: args2.summaryFallback,
|
|
19548
|
-
|
|
20171
|
+
onAttemptUsage: args2.onUsage,
|
|
20172
|
+
onPhase: (phase) => emitPhase(phase, initial ? "initial" : "in-loop")
|
|
19549
20173
|
});
|
|
19550
|
-
|
|
19551
|
-
args2.onUsage(compacted.usage);
|
|
19552
|
-
}
|
|
20174
|
+
lastCompactionOutcome = { result: compacted };
|
|
19553
20175
|
if (compacted.compressed) {
|
|
19554
20176
|
const rebuilt = composeProviderMessages({
|
|
19555
20177
|
prefix: args2.getWorkingPrefix(),
|
|
@@ -19564,16 +20186,65 @@ function createTurnCompactionController(args2) {
|
|
|
19564
20186
|
}
|
|
19565
20187
|
args2.replaceWorkingView(rebuilt.messages);
|
|
19566
20188
|
}
|
|
20189
|
+
if (compacted.compressed || initial) {
|
|
20190
|
+
args2.onSelectedSummary?.(compacted.selectedSummary ?? { outcome: initial ? "absent" : "unknown" });
|
|
20191
|
+
}
|
|
19567
20192
|
emitObservation(compacted);
|
|
19568
20193
|
} catch (error) {
|
|
20194
|
+
lastCompactionOutcome = { ...lastCompactionOutcome, error: classifySummaryError(error) };
|
|
19569
20195
|
console.warn("[localLoop] in-loop auto-compaction failed:", error);
|
|
19570
20196
|
}
|
|
19571
20197
|
};
|
|
19572
|
-
return { runInitial, maybeCompactInLoop };
|
|
20198
|
+
return { getLastCompactionOutcome: () => lastCompactionOutcome, runInitial, maybeCompactInLoop: () => prepareRequest(), forceCompact, prepareRequest };
|
|
19573
20199
|
}
|
|
19574
20200
|
|
|
19575
20201
|
// packages/agent-runtime/providerCallTelemetry.ts
|
|
19576
20202
|
import { createHash as createHash4 } from "node:crypto";
|
|
20203
|
+
var isCount = (v) => Number.isSafeInteger(v) && v >= 0;
|
|
20204
|
+
var isDigest = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
|
|
20205
|
+
var isMessageId = (v) => typeof v === "string" && /^(?:[0-9]{13}-[0-9]{3,6}|[0-9A-HJKMNP-TV-Z]{26}|local-[0-9]{1,12})$/.test(v);
|
|
20206
|
+
var isRecord2 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
20207
|
+
function projectContextProvenance(value) {
|
|
20208
|
+
if (!isRecord2(value) || value.schemaVersion !== 1) return void 0;
|
|
20209
|
+
const transports = ["unknown", "local-cli", "direct-openai-compatible", "codex-oauth", "codex-responses", "owner-oauth-proxy", "server-proxy"];
|
|
20210
|
+
const result4 = { schemaVersion: 1, transport: transports.includes(value.transport) ? value.transport : "unknown" };
|
|
20211
|
+
if (Array.isArray(value.phases)) {
|
|
20212
|
+
result4.phases = [];
|
|
20213
|
+
for (const item of value.phases.slice(0, 8)) {
|
|
20214
|
+
if (!isRecord2(item) || !["history-loaded", "summary-projected", "budget-trim", "final-request"].includes(item.phase)) continue;
|
|
20215
|
+
const phase = { phase: item.phase };
|
|
20216
|
+
if (["local", "remote", "partial", "none", "unknown"].includes(item.source)) phase.source = item.source;
|
|
20217
|
+
for (const key of ["count", "droppedCount"]) if (isCount(item[key])) phase[key] = item[key];
|
|
20218
|
+
for (const key of ["hash", "idsHash"]) if (isDigest(item[key])) phase[key] = item[key];
|
|
20219
|
+
for (const key of ["firstId", "lastId"]) if (isMessageId(item[key])) phase[key] = item[key];
|
|
20220
|
+
result4.phases.push(phase);
|
|
20221
|
+
}
|
|
20222
|
+
}
|
|
20223
|
+
if (isRecord2(value.summary)) {
|
|
20224
|
+
const input = value.summary;
|
|
20225
|
+
const outcomes = ["absent", "loaded", "generated", "invalid", "skipped", "failed", "unknown"];
|
|
20226
|
+
const summary = { outcome: outcomes.includes(input.outcome) ? input.outcome : "unknown" };
|
|
20227
|
+
for (const key of ["summaryId", "hash", "sourceHash"]) if (isDigest(input[key])) summary[key] = input[key];
|
|
20228
|
+
if (isMessageId(input.anchorId)) summary.anchorId = input.anchorId;
|
|
20229
|
+
if (isCount(input.sourceCount)) summary.sourceCount = input.sourceCount;
|
|
20230
|
+
result4.summary = summary;
|
|
20231
|
+
}
|
|
20232
|
+
return result4;
|
|
20233
|
+
}
|
|
20234
|
+
function contextPhase(phase, messages, options = {}) {
|
|
20235
|
+
const digest = (value) => createHash4("sha256").update(JSON.stringify(value) ?? "null").digest("hex");
|
|
20236
|
+
const ids = messages.map((m) => isRecord2(m) && isMessageId(m.cliMessageId) ? m.cliMessageId : null);
|
|
20237
|
+
return {
|
|
20238
|
+
phase,
|
|
20239
|
+
count: messages.length,
|
|
20240
|
+
hash: digest(messages),
|
|
20241
|
+
idsHash: digest(ids),
|
|
20242
|
+
...ids[0] ? { firstId: ids[0] } : {},
|
|
20243
|
+
...ids.at(-1) ? { lastId: ids.at(-1) } : {},
|
|
20244
|
+
...options.source ? { source: options.source } : {},
|
|
20245
|
+
...isCount(options.droppedCount) ? { droppedCount: options.droppedCount } : {}
|
|
20246
|
+
};
|
|
20247
|
+
}
|
|
19577
20248
|
var shortHash = (value) => createHash4("sha1").update(value).digest("hex").slice(0, 12);
|
|
19578
20249
|
var hashMessage = (message) => {
|
|
19579
20250
|
let text2;
|
|
@@ -19613,6 +20284,7 @@ function createDivergeTracker(max4 = DIVERGE_TRACKER_MAX_DIALOGS) {
|
|
|
19613
20284
|
var processDivergeTracker = createDivergeTracker();
|
|
19614
20285
|
function buildRequestTelemetry(args2) {
|
|
19615
20286
|
try {
|
|
20287
|
+
const provenance = projectContextProvenance(args2.provenance);
|
|
19616
20288
|
const hashes = args2.messages.map(hashMessage);
|
|
19617
20289
|
let toolResultChars = 0;
|
|
19618
20290
|
let toolResultCount = 0;
|
|
@@ -19628,6 +20300,7 @@ function buildRequestTelemetry(args2) {
|
|
|
19628
20300
|
const diverge = (args2.tracker ?? processDivergeTracker).observe(args2.dialogKey, hashes);
|
|
19629
20301
|
return {
|
|
19630
20302
|
...args2.toolsHash ? { toolsHash: args2.toolsHash } : {},
|
|
20303
|
+
...provenance ? { provenance } : {},
|
|
19631
20304
|
msgCount: args2.messages.length,
|
|
19632
20305
|
contentChars,
|
|
19633
20306
|
toolResultChars,
|
|
@@ -19647,13 +20320,23 @@ function hashToolDefinitions(tools) {
|
|
|
19647
20320
|
}
|
|
19648
20321
|
|
|
19649
20322
|
// packages/agent-runtime/localLoop.ts
|
|
20323
|
+
var LocalContextCoverageError = class extends Error {
|
|
20324
|
+
constructor(droppedCount, compactionUsage, diagnostics) {
|
|
20325
|
+
super("Context protection: history cannot fit without losing messages not represented in the sending context. This pending provider request was not sent; canonical history and pending input are retained. Restore summary access/provider availability and retry this same input, or select a larger context window. An invalid summary must be rebuilt before retrying.");
|
|
20326
|
+
this.droppedCount = droppedCount;
|
|
20327
|
+
this.compactionUsage = compactionUsage;
|
|
20328
|
+
this.diagnostics = diagnostics;
|
|
20329
|
+
this.name = "LocalContextCoverageError";
|
|
20330
|
+
}
|
|
20331
|
+
code = "LOCAL_CONTEXT_COVERAGE_REQUIRED";
|
|
20332
|
+
};
|
|
19650
20333
|
var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
|
|
19651
20334
|
var LLM_REQUEST_TIMEOUT = "LLM_REQUEST_TIMEOUT";
|
|
19652
20335
|
var DEFAULT_LLM_REQUEST_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
19653
20336
|
var DEFAULT_COMPACTION_TIMEOUT_MS = 60 * 1e3;
|
|
19654
20337
|
var DEFAULT_ROUND_BUDGET_WARNING_THRESHOLD = 25;
|
|
19655
20338
|
function buildRoundBudgetWarningPrompt(threshold) {
|
|
19656
|
-
return `[\u7CFB\u7EDF\u63D0\u793A] \u5F53\u524D\u5355\u6B21\u4EFB\u52A1\u7684\u8FDE\u7EED\u5DE5\u5177\u8C03\u7528\u5DF2\u8FBE ${threshold} \u8F6E\uFF0C\u8BF7\u8FDB\u884C\u8FDB\u5C55\u4E0E\u6210\u672C\u68C0\u67E5\uFF1A\u82E5\u5DF2\u6388\u6743\u76EE\u6807\u672A\u5B8C\u6210\u4E14\u6301\u7EED\u6709\u8FDB\u5C55\uFF0C\u5E94\u7EE7\u7EED\u63A8\u8FDB\uFF0C\u4E0D\u5F97\u4EC5\u56E0\u8F6E\u6570\u4EA4\u63A5\uFF1B\u4EC5\u5728\u76EE\u6807\u5DF2\u5B8C\u6210\u3001\u9047\u5230\u771F\u5B9E\u963B\u585E\u6216\
|
|
20339
|
+
return `[\u7CFB\u7EDF\u63D0\u793A] \u5F53\u524D\u5355\u6B21\u4EFB\u52A1\u7684\u8FDE\u7EED\u5DE5\u5177\u8C03\u7528\u5DF2\u8FBE ${threshold} \u8F6E\uFF0C\u8BF7\u8FDB\u884C\u8FDB\u5C55\u4E0E\u6210\u672C\u68C0\u67E5\uFF1A\u82E5\u5DF2\u6388\u6743\u76EE\u6807\u672A\u5B8C\u6210\u4E14\u6301\u7EED\u6709\u8FDB\u5C55\uFF0C\u5E94\u7EE7\u7EED\u63A8\u8FDB\uFF0C\u4E0D\u5F97\u4EC5\u56E0\u8F6E\u6570\u4EA4\u63A5\uFF1B\u4EC5\u5728\u76EE\u6807\u5DF2\u5B8C\u6210\u3001\u9047\u5230\u771F\u5B9E\u963B\u585E\u6216\u7528\u6237\u660E\u786E\u505C\u6B62\u65F6\u624D\u6536\u5C3E\uFF1B\u82E5\u8FDB\u5C55\u505C\u6EDE\uFF0C\u8BF7\u53CA\u65F6\u66F4\u6362\u7B56\u7565\u3002`;
|
|
19657
20340
|
}
|
|
19658
20341
|
var ROUND_BUDGET_WARNING_PROMPT = buildRoundBudgetWarningPrompt(
|
|
19659
20342
|
DEFAULT_ROUND_BUDGET_WARNING_THRESHOLD
|
|
@@ -19683,23 +20366,24 @@ var CONCURRENT_READONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
|
19683
20366
|
]);
|
|
19684
20367
|
function partitionToolCallsIntoBatches(toolCalls) {
|
|
19685
20368
|
const batches = [];
|
|
19686
|
-
let
|
|
19687
|
-
|
|
19688
|
-
|
|
19689
|
-
|
|
19690
|
-
|
|
19691
|
-
|
|
19692
|
-
|
|
19693
|
-
|
|
19694
|
-
|
|
19695
|
-
|
|
19696
|
-
|
|
19697
|
-
|
|
20369
|
+
let currentBatch = [];
|
|
20370
|
+
const flush2 = () => {
|
|
20371
|
+
if (currentBatch.length) batches.push({ isConcurrent: true, calls: currentBatch });
|
|
20372
|
+
currentBatch = [];
|
|
20373
|
+
};
|
|
20374
|
+
for (let index = 0; index < toolCalls.length; index += 1) {
|
|
20375
|
+
const toolCall = toolCalls[index];
|
|
20376
|
+
const contract = resolveToolExecutionContract(toolCall.function.name);
|
|
20377
|
+
const isReadOnly = contract.interaction === "none" && contract.concurrency === "safe";
|
|
20378
|
+
const legacyRead = contract.concurrency === "exclusive" && contract.interaction === "unknown" && CONCURRENT_READONLY_TOOLS.has(toolCall.function.name);
|
|
20379
|
+
if (toolCall.function.name === "startAgentRun" || !isReadOnly && !legacyRead) {
|
|
20380
|
+
flush2();
|
|
20381
|
+
batches.push({ isConcurrent: false, calls: [{ index, toolCall }] });
|
|
20382
|
+
continue;
|
|
19698
20383
|
}
|
|
20384
|
+
currentBatch.push({ index, toolCall });
|
|
19699
20385
|
}
|
|
19700
|
-
|
|
19701
|
-
batches.push({ isConcurrent: true, calls: currentReadBatch });
|
|
19702
|
-
}
|
|
20386
|
+
flush2();
|
|
19703
20387
|
return batches;
|
|
19704
20388
|
}
|
|
19705
20389
|
function resolveLlmRequestTimeoutMs(input) {
|
|
@@ -19708,7 +20392,7 @@ function resolveLlmRequestTimeoutMs(input) {
|
|
|
19708
20392
|
}
|
|
19709
20393
|
function resolveCompactionTimeoutMs(input) {
|
|
19710
20394
|
const raw = input.compactionTimeoutMs;
|
|
19711
|
-
return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_COMPACTION_TIMEOUT_MS;
|
|
20395
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? Math.min(raw, DEFAULT_COMPACTION_TIMEOUT_MS) : DEFAULT_COMPACTION_TIMEOUT_MS;
|
|
19712
20396
|
}
|
|
19713
20397
|
function readHostCompactionSummaryFallback(adapter) {
|
|
19714
20398
|
const value = adapter.compactionSummaryFallback;
|
|
@@ -19833,6 +20517,10 @@ function attachUsageRecordsToError(error, usageRecords) {
|
|
|
19833
20517
|
}
|
|
19834
20518
|
async function persistFailedLocalTurn(args2) {
|
|
19835
20519
|
const errorMessage = toErrorMessage(args2.error);
|
|
20520
|
+
const businessCompletion = evaluateTaskExecutionContract(args2.input.taskExecutionContract, {
|
|
20521
|
+
stopped: args2.input.abortSignal?.aborted || args2.error instanceof Error && args2.error.code === LOCAL_TURN_ABORTED_CODE,
|
|
20522
|
+
executionFailed: true
|
|
20523
|
+
});
|
|
19836
20524
|
try {
|
|
19837
20525
|
const saved = await args2.adapter.saveTurn({
|
|
19838
20526
|
agentKey: args2.agentKey,
|
|
@@ -19843,6 +20531,7 @@ async function persistFailedLocalTurn(args2) {
|
|
|
19843
20531
|
toolCallCount: args2.toolCallCount ?? 0,
|
|
19844
20532
|
error: true,
|
|
19845
20533
|
errorMessage,
|
|
20534
|
+
...businessCompletion ? { businessCompletion } : {},
|
|
19846
20535
|
...args2.usage ? { usage: args2.usage } : {}
|
|
19847
20536
|
},
|
|
19848
20537
|
...args2.accountingUsage ? { accountingUsage: args2.accountingUsage } : {},
|
|
@@ -19876,6 +20565,18 @@ async function loadAdapterDialogHistory(adapter, dialogId, options) {
|
|
|
19876
20565
|
}
|
|
19877
20566
|
return { messages: await adapter.loadDialogHistory(dialogId) };
|
|
19878
20567
|
}
|
|
20568
|
+
function combineRollbackError(primary, rollbackError) {
|
|
20569
|
+
const primaryError = primary instanceof Error ? primary : new Error(String(primary));
|
|
20570
|
+
const rollbackErr = rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError));
|
|
20571
|
+
const combined = new AggregateError(
|
|
20572
|
+
[primaryError, rollbackErr],
|
|
20573
|
+
`${primaryError.message} (additionally, injection rollback failed: ${rollbackErr.message})`
|
|
20574
|
+
);
|
|
20575
|
+
if (primary && typeof primary === "object") {
|
|
20576
|
+
Object.assign(combined, primary);
|
|
20577
|
+
}
|
|
20578
|
+
return combined;
|
|
20579
|
+
}
|
|
19879
20580
|
async function runLocalAgentTurn(input) {
|
|
19880
20581
|
const legacyCallbacks = {
|
|
19881
20582
|
onLoopEvent: input.onLoopEvent,
|
|
@@ -19889,17 +20590,6 @@ async function runLocalAgentTurn(input) {
|
|
|
19889
20590
|
observationBoundary.attachCallbacks(legacyCallbacks);
|
|
19890
20591
|
}
|
|
19891
20592
|
const loopTiming = createLoopTiming();
|
|
19892
|
-
const subtaskBudgetClock = input.subtaskBudgetNow ?? (() => Date.now());
|
|
19893
|
-
const subtaskBudgetLimits = {
|
|
19894
|
-
maxToolCalls: input.subtaskMaxToolCalls ?? input.subtaskBudgetLimits?.maxToolCalls ?? DEFAULT_SUBTASK_MAX_TOOL_CALLS,
|
|
19895
|
-
maxWallClockMs: input.subtaskMaxWallClockMs ?? input.subtaskBudgetLimits?.maxWallClockMs ?? DEFAULT_SUBTASK_MAX_WALL_CLOCK_MS
|
|
19896
|
-
};
|
|
19897
|
-
const subtaskBudgetTracker = input.runKind === "subtask" ? createSubtaskBudgetTracker({
|
|
19898
|
-
limits: subtaskBudgetLimits,
|
|
19899
|
-
now: subtaskBudgetClock,
|
|
19900
|
-
// 墙钟从 run 开始计(含 provider 初始化与首轮前的准备)。
|
|
19901
|
-
startedAtMs: subtaskBudgetClock()
|
|
19902
|
-
}) : null;
|
|
19903
20593
|
try {
|
|
19904
20594
|
loopTiming.mark("turnStart", 0);
|
|
19905
20595
|
let agentConfig = await input.adapter.loadAgentConfig(input.agentRef);
|
|
@@ -19987,7 +20677,8 @@ async function runLocalAgentTurn(input) {
|
|
|
19987
20677
|
if (input.strictContinueHistory && (loaded.source === "none" || loaded.source === "partial")) {
|
|
19988
20678
|
throw new Error(`Strict continuation history unavailable: ${loaded.source}`);
|
|
19989
20679
|
}
|
|
19990
|
-
|
|
20680
|
+
const currentIds = new Set(input.userMessages?.map((message) => message.cliMessageId));
|
|
20681
|
+
history = loaded.messages.filter((message) => !currentIds.has(message.cliMessageId));
|
|
19991
20682
|
dialogHistorySource = loaded.source;
|
|
19992
20683
|
}
|
|
19993
20684
|
} catch (error) {
|
|
@@ -20073,6 +20764,9 @@ async function runLocalAgentTurn(input) {
|
|
|
20073
20764
|
// 平台风控纪律:无条件系统层块,沿用 session 占位约定。
|
|
20074
20765
|
{ content: PLATFORM_RISK_CONTROL_RULE, cacheScope: "session" },
|
|
20075
20766
|
{ content: buildConsultationModeBlock(), cacheScope: "session" },
|
|
20767
|
+
// Git 任务隔离:系统层固定前置,四条装配线同序(请教模式之后、身份信息之前;
|
|
20768
|
+
// skill 配置 disabled 也注入)。
|
|
20769
|
+
{ content: WORKTREE_ISOLATION_PRELUDE, cacheScope: "session" },
|
|
20076
20770
|
{ content: identityBlock, cacheScope: "session" },
|
|
20077
20771
|
...guidanceScopes,
|
|
20078
20772
|
// 回复行为准则:local 线(CLI 非交互 / 桌面 / TUI)的唯一注入边界。
|
|
@@ -20092,19 +20786,29 @@ async function runLocalAgentTurn(input) {
|
|
|
20092
20786
|
let resolvedSummaryProvider;
|
|
20093
20787
|
const resolveSummaryProviderOnce = async () => {
|
|
20094
20788
|
if (!resolvedSummaryProvider) {
|
|
20095
|
-
|
|
20789
|
+
const provider = await input.adapter.resolveProvider(agentConfig, {
|
|
20790
|
+
textOnly: true,
|
|
20096
20791
|
toolNames: [],
|
|
20097
20792
|
prompt: ""
|
|
20098
20793
|
});
|
|
20794
|
+
if (provider.textOnly !== true) {
|
|
20795
|
+
throw new Error("auto-compaction requires an isolated text-only provider");
|
|
20796
|
+
}
|
|
20797
|
+
resolvedSummaryProvider = provider;
|
|
20099
20798
|
}
|
|
20100
20799
|
return resolvedSummaryProvider;
|
|
20101
20800
|
};
|
|
20102
20801
|
const contextWindow = resolveAgentContextWindow(agentConfig);
|
|
20103
20802
|
const compressionTriggerRatio = resolveCompressionTriggerRatio(contextWindow);
|
|
20803
|
+
let selectedSummary = { outcome: "unknown" };
|
|
20804
|
+
let summaryProjectedPhase = contextPhase("summary-projected", history);
|
|
20805
|
+
const historyLoadedPhase = contextPhase("history-loaded", history, { source: dialogHistorySource ?? "unknown" });
|
|
20104
20806
|
const compaction = createTurnCompactionController({
|
|
20105
20807
|
adapter: input.adapter,
|
|
20106
20808
|
continueDialogId: input.continueDialogId,
|
|
20107
20809
|
model: agentConfig.model,
|
|
20810
|
+
provider: agentConfig.provider,
|
|
20811
|
+
providerEndpoint: agentConfig.customProviderUrl,
|
|
20108
20812
|
resolveProvider: resolveSummaryProviderOnce,
|
|
20109
20813
|
contextWindow,
|
|
20110
20814
|
compressionTriggerRatio,
|
|
@@ -20125,19 +20829,18 @@ async function runLocalAgentTurn(input) {
|
|
|
20125
20829
|
)
|
|
20126
20830
|
],
|
|
20127
20831
|
getWorkingPrefix: () => transcript.working().slice(0, prefixCount),
|
|
20128
|
-
|
|
20832
|
+
onSelectedSummary: (summary) => {
|
|
20833
|
+
selectedSummary = summary;
|
|
20834
|
+
},
|
|
20835
|
+
replaceWorkingView: (next) => {
|
|
20836
|
+
transcript.replaceWorkingHistory(next);
|
|
20837
|
+
summaryProjectedPhase = contextPhase("summary-projected", next);
|
|
20838
|
+
},
|
|
20129
20839
|
contextReferenceResolver: input.adapter.host === "cli" ? input.contextReferenceResolver : void 0,
|
|
20130
20840
|
onUsage: (usage) => usageLedger.addCompaction(usage)
|
|
20131
20841
|
});
|
|
20132
|
-
|
|
20133
|
-
|
|
20134
|
-
const initialCompactionUsage = initialCompaction.usage;
|
|
20135
|
-
loopTiming.mark("maybeAutoCompactLocalHistory", 0);
|
|
20136
|
-
const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model, contextWindow);
|
|
20137
|
-
if (trimmedHistory.droppedCount > 0) {
|
|
20138
|
-
history = trimmedHistory.history;
|
|
20139
|
-
}
|
|
20140
|
-
loopTiming.mark("trimHistoryToContextBudget", 0);
|
|
20842
|
+
throwIfAborted(input);
|
|
20843
|
+
let budgetTrimPhase = contextPhase("budget-trim", history, { droppedCount: 0 });
|
|
20141
20844
|
const builtMessages = buildMessages({
|
|
20142
20845
|
prompt: agentConfig.prompt,
|
|
20143
20846
|
contextBlockScopes: mergedContextBlockScopes,
|
|
@@ -20169,6 +20872,14 @@ async function runLocalAgentTurn(input) {
|
|
|
20169
20872
|
...msg,
|
|
20170
20873
|
content: truncateToolOutputForContext(msg.content, contextWindow)
|
|
20171
20874
|
} : msg;
|
|
20875
|
+
if (input.userMessages?.length) {
|
|
20876
|
+
const currentInputStart = builtMessages.prefixCount + history.length;
|
|
20877
|
+
const sanitizedUsers = await Promise.all(input.userMessages.map(async (message) => ({
|
|
20878
|
+
...message,
|
|
20879
|
+
content: await sanitizeInbound(message.content)
|
|
20880
|
+
})));
|
|
20881
|
+
messages.splice(currentInputStart, messages.length - currentInputStart, ...sanitizedUsers);
|
|
20882
|
+
}
|
|
20172
20883
|
const acceptToolImages = createToolImageLedger();
|
|
20173
20884
|
const transcript = createTurnTranscript({
|
|
20174
20885
|
initialWorking: messages,
|
|
@@ -20178,7 +20889,9 @@ async function runLocalAgentTurn(input) {
|
|
|
20178
20889
|
});
|
|
20179
20890
|
const userInputText = extractUserInputText(input.input);
|
|
20180
20891
|
let toolCallCount = 0;
|
|
20892
|
+
let requestCalibrationRatio = 1;
|
|
20181
20893
|
let result4 = { content: "" };
|
|
20894
|
+
let stopReason;
|
|
20182
20895
|
const usageLedger = createTurnUsageLedger({
|
|
20183
20896
|
model: agentConfig.model,
|
|
20184
20897
|
provider: agentConfig.provider,
|
|
@@ -20187,77 +20900,126 @@ async function runLocalAgentTurn(input) {
|
|
|
20187
20900
|
stablePrefixEstimatedTokens: builtMessages.stablePrefixEstimatedTokens
|
|
20188
20901
|
} : {}
|
|
20189
20902
|
});
|
|
20190
|
-
if (initialCompactionUsage) usageLedger.addCompaction(initialCompactionUsage);
|
|
20191
20903
|
let loopError;
|
|
20904
|
+
let consumedInjectedMessages = false;
|
|
20192
20905
|
let round = 0;
|
|
20193
|
-
let budgetExhaustion = null;
|
|
20194
|
-
const executedToolNameLog = [];
|
|
20195
|
-
const markBudgetExhausted = () => {
|
|
20196
|
-
if (!subtaskBudgetTracker || budgetExhaustion) return;
|
|
20197
|
-
const exhaustion = subtaskBudgetTracker.exhaustion();
|
|
20198
|
-
if (!exhaustion) return;
|
|
20199
|
-
budgetExhaustion = exhaustion;
|
|
20200
|
-
emitLoopEvent(observationBoundary, {
|
|
20201
|
-
kind: "budget-exhausted",
|
|
20202
|
-
limit: exhaustion.limit,
|
|
20203
|
-
atMs: exhaustion.atMs,
|
|
20204
|
-
maxToolCalls: exhaustion.limits.maxToolCalls,
|
|
20205
|
-
maxWallClockMs: exhaustion.limits.maxWallClockMs,
|
|
20206
|
-
toolCallsExecuted: exhaustion.toolCallsExecuted,
|
|
20207
|
-
elapsedMs: exhaustion.elapsedMs,
|
|
20208
|
-
round
|
|
20209
|
-
});
|
|
20210
|
-
};
|
|
20211
20906
|
let emptyAssistantRepairPending = false;
|
|
20212
20907
|
let emptyAssistantRepairUsed = false;
|
|
20213
20908
|
let reasoningEmptyRepairCount = 0;
|
|
20214
20909
|
let skipFinalAppend = false;
|
|
20215
20910
|
let partialContent = "";
|
|
20216
20911
|
const progressGuard = createLocalLoopProgressGuard(input.progressGuardConfig);
|
|
20217
|
-
|
|
20218
|
-
|
|
20219
|
-
|
|
20220
|
-
markBudgetExhausted();
|
|
20221
|
-
return false;
|
|
20912
|
+
let pendingInjectionCommits = [];
|
|
20913
|
+
let inFlightTransactions = [];
|
|
20914
|
+
let rollbackInjectionCommits = async () => {
|
|
20222
20915
|
};
|
|
20223
20916
|
try {
|
|
20224
20917
|
const provider = await resolveProviderOnce();
|
|
20225
|
-
const applyPendingInjections = () => {
|
|
20918
|
+
const applyPendingInjections = async () => {
|
|
20226
20919
|
if (!input.drainInjections) return false;
|
|
20227
|
-
|
|
20228
|
-
try {
|
|
20229
|
-
pending = input.drainInjections() ?? [];
|
|
20230
|
-
} catch (error) {
|
|
20231
|
-
console.warn("[localLoop] drainInjections failed:", error);
|
|
20232
|
-
return false;
|
|
20233
|
-
}
|
|
20920
|
+
const pending = await input.drainInjections() ?? [];
|
|
20234
20921
|
let injected = false;
|
|
20235
|
-
for (const
|
|
20236
|
-
if (typeof
|
|
20237
|
-
|
|
20238
|
-
|
|
20922
|
+
for (const entry of pending) {
|
|
20923
|
+
if (typeof entry === "string") {
|
|
20924
|
+
if (!entry.trim()) continue;
|
|
20925
|
+
transcript.push({ role: "user", content: scrubSecrets(entry).cleaned });
|
|
20926
|
+
} else if (entry && typeof entry === "object" && "messages" in entry) {
|
|
20927
|
+
for (const message of entry.messages) {
|
|
20928
|
+
const content = typeof message.content === "string" ? scrubSecrets(message.content).cleaned : Array.isArray(message.content) ? message.content.map((part) => part?.type === "text" && typeof part.text === "string" ? { ...part, text: scrubSecrets(part.text).cleaned } : part) : message.content;
|
|
20929
|
+
transcript.push({
|
|
20930
|
+
role: "user",
|
|
20931
|
+
content,
|
|
20932
|
+
...message.cliMessageId ? { cliMessageId: message.cliMessageId } : {}
|
|
20933
|
+
});
|
|
20934
|
+
}
|
|
20935
|
+
pendingInjectionCommits.push({ commit: entry.commit, rollback: entry.rollback, messages: entry.messages });
|
|
20936
|
+
} else if (entry && typeof entry === "object" && "content" in entry) {
|
|
20937
|
+
const content = typeof entry.content === "string" ? scrubSecrets(entry.content).cleaned : Array.isArray(entry.content) ? entry.content.map((part) => part?.type === "text" && typeof part.text === "string" ? { ...part, text: scrubSecrets(part.text).cleaned } : part) : entry.content;
|
|
20938
|
+
transcript.push({
|
|
20939
|
+
role: "user",
|
|
20940
|
+
content,
|
|
20941
|
+
...entry.cliMessageId ? { cliMessageId: entry.cliMessageId } : {}
|
|
20942
|
+
});
|
|
20943
|
+
} else {
|
|
20944
|
+
continue;
|
|
20945
|
+
}
|
|
20946
|
+
consumedInjectedMessages = true;
|
|
20239
20947
|
injected = true;
|
|
20240
20948
|
}
|
|
20241
20949
|
return injected;
|
|
20242
20950
|
};
|
|
20951
|
+
rollbackInjectionCommits = async (transactions) => {
|
|
20952
|
+
const errors = [];
|
|
20953
|
+
for (const transaction of transactions.slice().reverse()) {
|
|
20954
|
+
try {
|
|
20955
|
+
await transaction.rollback();
|
|
20956
|
+
} catch (rollbackError) {
|
|
20957
|
+
errors.push(rollbackError);
|
|
20958
|
+
}
|
|
20959
|
+
const ids = new Set(
|
|
20960
|
+
transaction.messages.map((message) => message.cliMessageId).filter((id) => Boolean(id))
|
|
20961
|
+
);
|
|
20962
|
+
if (ids.size > 0) {
|
|
20963
|
+
transcript.retract((msg) => {
|
|
20964
|
+
const id = msg.cliMessageId;
|
|
20965
|
+
return typeof id === "string" && ids.has(id);
|
|
20966
|
+
});
|
|
20967
|
+
}
|
|
20968
|
+
}
|
|
20969
|
+
if (errors.length > 0) {
|
|
20970
|
+
throw new Error(
|
|
20971
|
+
`injection rollback failed: ${errors.map((error) => error instanceof Error ? error.message : String(error)).join("; ")}`
|
|
20972
|
+
);
|
|
20973
|
+
}
|
|
20974
|
+
};
|
|
20243
20975
|
const newDialogTelemetryKey = `new:${crypto.randomUUID()}`;
|
|
20244
20976
|
let roundBudgetWarningInjected = false;
|
|
20245
|
-
let subtaskToolBudgetWarningInjected = false;
|
|
20246
20977
|
const roundWarningThreshold = input.roundBudgetWarningThreshold ?? DEFAULT_ROUND_BUDGET_WARNING_THRESHOLD;
|
|
20247
20978
|
while (true) {
|
|
20248
20979
|
partialContent = "";
|
|
20249
20980
|
throwIfAborted(input);
|
|
20250
20981
|
loopTiming.mark("roundStart", round);
|
|
20251
|
-
applyPendingInjections();
|
|
20982
|
+
await applyPendingInjections();
|
|
20252
20983
|
if (roundWarningThreshold > 0 && round >= roundWarningThreshold && !roundBudgetWarningInjected) {
|
|
20253
20984
|
const prompt = buildRoundBudgetWarningPrompt(roundWarningThreshold);
|
|
20254
20985
|
transcript.push({ role: "user", content: prompt });
|
|
20255
20986
|
roundBudgetWarningInjected = true;
|
|
20256
20987
|
}
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
|
|
20988
|
+
const projectRequest = (source) => {
|
|
20989
|
+
const prepared = prepareMessagesForProviderCall(source);
|
|
20990
|
+
const base = filterImagePartsFromMessages(prepared.messages, supportsImages);
|
|
20991
|
+
return emptyAssistantRepairPending ? [...base, { role: "user", content: EMPTY_ASSISTANT_REPAIR_PROMPT }] : base;
|
|
20992
|
+
};
|
|
20993
|
+
const admissionProvider = await resolveProviderOnce();
|
|
20994
|
+
throwIfAborted(input);
|
|
20995
|
+
const requestOverBudget = (messages2) => !evaluateLocalRequestBudget({
|
|
20996
|
+
messages: messages2,
|
|
20997
|
+
contextWindow,
|
|
20998
|
+
descriptor: admissionProvider.requestBudget,
|
|
20999
|
+
calibrationRatio: requestCalibrationRatio
|
|
21000
|
+
}).fitsEstimate;
|
|
21001
|
+
const availableHistoryTokens = () => {
|
|
21002
|
+
const decision = evaluateLocalRequestBudget({
|
|
21003
|
+
messages: [],
|
|
21004
|
+
contextWindow,
|
|
21005
|
+
descriptor: admissionProvider.requestBudget,
|
|
21006
|
+
calibrationRatio: requestCalibrationRatio
|
|
21007
|
+
});
|
|
21008
|
+
const prefixTokens = estimateLocalRequestInput(projectRequest(transcript.working().slice(0, prefixCount)));
|
|
21009
|
+
return Math.max(0, Math.floor(decision.availableInputTokens / requestCalibrationRatio) - prefixTokens - (admissionProvider.requestBudget?.toolSchemaTokens ?? 0));
|
|
21010
|
+
};
|
|
21011
|
+
const historyTokensBeforeCompaction = Math.ceil(estimateLocalRequestInput(
|
|
21012
|
+
projectRequest(transcript.working()).slice(prefixCount)
|
|
21013
|
+
) * requestCalibrationRatio);
|
|
21014
|
+
await compaction.prepareRequest((source) => {
|
|
21015
|
+
const projected = composeProviderMessages({
|
|
21016
|
+
prefix: transcript.working().slice(0, prefixCount),
|
|
21017
|
+
history: source,
|
|
21018
|
+
contextReferenceResolver: input.adapter.host === "cli" ? input.contextReferenceResolver : void 0
|
|
21019
|
+
});
|
|
21020
|
+
return requestOverBudget(projectRequest(projected.messages));
|
|
21021
|
+
}, round === 0, availableHistoryTokens);
|
|
21022
|
+
throwIfAborted(input);
|
|
20261
21023
|
const preparedMessages = prepareMessagesForProviderCall(transcript.working());
|
|
20262
21024
|
if (!supportsImages && hasImageInRuntimeMessages(preparedMessages.messages) && !imageDowngradeEmitted) {
|
|
20263
21025
|
emitLoopEvent(observationBoundary, {
|
|
@@ -20267,11 +21029,27 @@ async function runLocalAgentTurn(input) {
|
|
|
20267
21029
|
});
|
|
20268
21030
|
imageDowngradeEmitted = true;
|
|
20269
21031
|
}
|
|
20270
|
-
const
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
|
|
21032
|
+
const requestMessages = projectRequest(transcript.working());
|
|
21033
|
+
if (requestOverBudget(requestMessages)) {
|
|
21034
|
+
const budget = evaluateLocalRequestBudget({
|
|
21035
|
+
messages: requestMessages,
|
|
21036
|
+
contextWindow,
|
|
21037
|
+
descriptor: admissionProvider.requestBudget,
|
|
21038
|
+
calibrationRatio: requestCalibrationRatio
|
|
21039
|
+
});
|
|
21040
|
+
const largestMessageTokens = requestMessages.reduce((largest, message) => Math.max(
|
|
21041
|
+
largest,
|
|
21042
|
+
Math.ceil(estimateLocalRequestInput([message]) * requestCalibrationRatio)
|
|
21043
|
+
), 0);
|
|
21044
|
+
throw new LocalContextCoverageError(0, void 0, classifyContextRefusal({
|
|
21045
|
+
outcome: compaction.getLastCompactionOutcome(),
|
|
21046
|
+
historyTokens: historyTokensBeforeCompaction,
|
|
21047
|
+
budget: budget.availableInputTokens,
|
|
21048
|
+
droppedCount: 0,
|
|
21049
|
+
largestMessageTokens
|
|
21050
|
+
}));
|
|
21051
|
+
}
|
|
21052
|
+
budgetTrimPhase = contextPhase("budget-trim", requestMessages, { droppedCount: 0 });
|
|
20275
21053
|
const contextMetrics = {
|
|
20276
21054
|
...preparedMessages.metrics,
|
|
20277
21055
|
messageCount: requestMessages.length,
|
|
@@ -20299,63 +21077,109 @@ async function runLocalAgentTurn(input) {
|
|
|
20299
21077
|
// 无 dialogId 的新对话用本 turn 唯一键,避免不同新对话共用一个槽误报漂移。
|
|
20300
21078
|
dialogKey: input.continueDialogId || newDialogTelemetryKey,
|
|
20301
21079
|
messages: requestMessages,
|
|
21080
|
+
provenance: {
|
|
21081
|
+
schemaVersion: 1,
|
|
21082
|
+
transport: provider.transport ?? "unknown",
|
|
21083
|
+
phases: [historyLoadedPhase, summaryProjectedPhase, budgetTrimPhase, contextPhase("final-request", requestMessages)],
|
|
21084
|
+
summary: selectedSummary
|
|
21085
|
+
},
|
|
20302
21086
|
toolsHash: safeToolNamesHash(agentTools)
|
|
20303
21087
|
});
|
|
20304
|
-
if (!budgetAdmissionGate()) {
|
|
20305
|
-
break;
|
|
20306
|
-
}
|
|
20307
21088
|
resetToolImageDelivery(requestMessages.flatMap(toolImages));
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
21089
|
+
if (pendingInjectionCommits.length > 0) {
|
|
21090
|
+
inFlightTransactions = pendingInjectionCommits.splice(0);
|
|
21091
|
+
try {
|
|
21092
|
+
for (const transaction of inFlightTransactions) await transaction.commit();
|
|
21093
|
+
if (input.abortSignal?.aborted) throw buildAbortedError();
|
|
21094
|
+
} catch (error) {
|
|
21095
|
+
const toRollback = inFlightTransactions;
|
|
21096
|
+
inFlightTransactions = [];
|
|
21097
|
+
try {
|
|
21098
|
+
await rollbackInjectionCommits(toRollback);
|
|
21099
|
+
} catch (rbErr) {
|
|
21100
|
+
throw combineRollbackError(error, rbErr);
|
|
21101
|
+
}
|
|
21102
|
+
throw error;
|
|
21103
|
+
}
|
|
21104
|
+
}
|
|
21105
|
+
let providerInvoked = false;
|
|
21106
|
+
try {
|
|
21107
|
+
result4 = await runCompleteWithTimeout({
|
|
21108
|
+
provider: { complete: (messages2, options) => {
|
|
21109
|
+
providerInvoked = true;
|
|
21110
|
+
inFlightTransactions = [];
|
|
21111
|
+
return provider.complete(messages2, options);
|
|
21112
|
+
} },
|
|
21113
|
+
messages: requestMessages,
|
|
21114
|
+
options: {
|
|
21115
|
+
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
21116
|
+
// 用户取消信号穿进 provider options:providerStreamRetry 据此在
|
|
21117
|
+
// 取消后跳过重试,provider 分支(如 antigravity/openai-compatible)
|
|
21118
|
+
// 也可把 fetch 绑定到同一信号,实现真正的传输层取消。
|
|
21119
|
+
...input.abortSignal ? { signal: input.abortSignal } : {},
|
|
21120
|
+
// 计费归因:续聊轮次带上 dialogId,platform proxy 才能把 token 记录
|
|
21121
|
+
// 归到具体对话而不是 chat-proxy 兜底桶。新对话首轮 id 尚未分配。
|
|
21122
|
+
...input.continueDialogId ? { dialogId: input.continueDialogId } : {},
|
|
21123
|
+
...shouldStreamDeltas ? { onTextDelta: (chunk) => {
|
|
21124
|
+
llmStreamActivity += 1;
|
|
21125
|
+
partialContent += chunk;
|
|
21126
|
+
observationBoundary.emit({
|
|
21127
|
+
kind: "text-delta",
|
|
21128
|
+
chunk,
|
|
21129
|
+
round,
|
|
21130
|
+
atMs: Date.now()
|
|
21131
|
+
});
|
|
21132
|
+
} } : {},
|
|
21133
|
+
...shouldStreamReasoning ? { onReasoningDelta: (chunk) => {
|
|
21134
|
+
llmStreamActivity += 1;
|
|
21135
|
+
observationBoundary.emit({
|
|
21136
|
+
kind: "reasoning-delta",
|
|
21137
|
+
chunk,
|
|
21138
|
+
round,
|
|
21139
|
+
atMs: Date.now()
|
|
21140
|
+
});
|
|
21141
|
+
} } : {},
|
|
21142
|
+
...shouldPassToolEvents ? { onToolEvent: (event) => {
|
|
21143
|
+
llmStreamActivity += 1;
|
|
21144
|
+
observationBoundary.emit({
|
|
21145
|
+
kind: "tool-event",
|
|
21146
|
+
event,
|
|
21147
|
+
round,
|
|
21148
|
+
atMs: Date.now()
|
|
21149
|
+
});
|
|
21150
|
+
} } : {},
|
|
21151
|
+
...shouldPassToolEvents ? { toolEventRound: round } : {}
|
|
21152
|
+
},
|
|
20312
21153
|
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
20313
|
-
|
|
20314
|
-
|
|
20315
|
-
|
|
20316
|
-
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
|
|
20324
|
-
|
|
20325
|
-
|
|
20326
|
-
|
|
20327
|
-
|
|
20328
|
-
|
|
20329
|
-
}
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
|
|
20333
|
-
|
|
20334
|
-
|
|
20335
|
-
|
|
20336
|
-
|
|
20337
|
-
|
|
20338
|
-
}
|
|
20339
|
-
|
|
20340
|
-
|
|
20341
|
-
|
|
20342
|
-
kind: "tool-event",
|
|
20343
|
-
event,
|
|
20344
|
-
round,
|
|
20345
|
-
atMs: Date.now()
|
|
20346
|
-
});
|
|
20347
|
-
} } : {},
|
|
20348
|
-
...shouldPassToolEvents ? { toolEventRound: round } : {}
|
|
20349
|
-
},
|
|
20350
|
-
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
20351
|
-
activityVersion: () => llmStreamActivity,
|
|
20352
|
-
round,
|
|
20353
|
-
input,
|
|
20354
|
-
boundary: observationBoundary,
|
|
20355
|
-
context: contextMetrics,
|
|
20356
|
-
providerName: agentConfig.provider,
|
|
20357
|
-
model: provider.model
|
|
20358
|
-
});
|
|
21154
|
+
activityVersion: () => llmStreamActivity,
|
|
21155
|
+
round,
|
|
21156
|
+
input,
|
|
21157
|
+
boundary: observationBoundary,
|
|
21158
|
+
context: contextMetrics,
|
|
21159
|
+
providerName: agentConfig.provider,
|
|
21160
|
+
model: provider.model
|
|
21161
|
+
});
|
|
21162
|
+
} catch (error) {
|
|
21163
|
+
if (!providerInvoked && inFlightTransactions.length > 0) {
|
|
21164
|
+
const toRollback = inFlightTransactions;
|
|
21165
|
+
inFlightTransactions = [];
|
|
21166
|
+
try {
|
|
21167
|
+
await rollbackInjectionCommits(toRollback);
|
|
21168
|
+
} catch (rbErr) {
|
|
21169
|
+
error = combineRollbackError(error, rbErr);
|
|
21170
|
+
}
|
|
21171
|
+
}
|
|
21172
|
+
if (providerInvoked) usageLedger.recordProviderCall({
|
|
21173
|
+
model: agentConfig.model,
|
|
21174
|
+
telemetry: {
|
|
21175
|
+
...requestTelemetry,
|
|
21176
|
+
round,
|
|
21177
|
+
endTs: Date.now(),
|
|
21178
|
+
requestState: input.abortSignal?.aborted ? "cancelled" : "failed"
|
|
21179
|
+
}
|
|
21180
|
+
});
|
|
21181
|
+
throw error;
|
|
21182
|
+
}
|
|
20359
21183
|
acceptToolImages.discard(requestMessages.flatMap(toolImages).filter((image) => toolImageDelivery(image) === "impossible"));
|
|
20360
21184
|
acceptToolImages.commit(
|
|
20361
21185
|
requestMessages.flatMap(toolImages).filter((image) => toolImageDelivery(image) === "delivered"),
|
|
@@ -20365,13 +21189,25 @@ async function runLocalAgentTurn(input) {
|
|
|
20365
21189
|
const pending = toolImages(message).filter((image) => supportsImages && !toolImageDelivery(image));
|
|
20366
21190
|
return pending.length ? { ...message, [TOOL_IMAGES]: pending } : stripToolImages(message);
|
|
20367
21191
|
}));
|
|
21192
|
+
const actualInput = normalizeUsage(result4.usage).input_tokens;
|
|
21193
|
+
const estimatedInput = estimateLocalRequestInput(
|
|
21194
|
+
requestMessages,
|
|
21195
|
+
admissionProvider.requestBudget?.toolSchemaTokens ?? 0
|
|
21196
|
+
);
|
|
21197
|
+
requestCalibrationRatio = updateLocalRequestCalibration(requestCalibrationRatio, actualInput, estimatedInput);
|
|
20368
21198
|
loopTiming.mark("llmCall", round);
|
|
20369
21199
|
usageLedger.recordProviderCall({
|
|
20370
21200
|
usage: result4.usage,
|
|
20371
21201
|
model: result4.model,
|
|
20372
21202
|
provider: result4.provider,
|
|
20373
|
-
telemetry: finalizeCallTelemetry(requestTelemetry, result4, round, callStartedAt)
|
|
21203
|
+
telemetry: { ...finalizeCallTelemetry(requestTelemetry, result4, round, callStartedAt), requestState: "completed" }
|
|
20374
21204
|
});
|
|
21205
|
+
if (!result4.content && result4.output?.some((block) => block.type === "text") && !result4.output.some((block) => block.type === "toolCall")) {
|
|
21206
|
+
result4 = {
|
|
21207
|
+
...result4,
|
|
21208
|
+
content: result4.output.filter((block) => block.type === "text").map((block) => block.text).join("")
|
|
21209
|
+
};
|
|
21210
|
+
}
|
|
20375
21211
|
const assistantGuardVerdict = progressGuard.observeAssistantResponse(result4);
|
|
20376
21212
|
if (assistantGuardVerdict.action === "stall") {
|
|
20377
21213
|
emitLoopEvent(observationBoundary, {
|
|
@@ -20389,11 +21225,11 @@ async function runLocalAgentTurn(input) {
|
|
|
20389
21225
|
};
|
|
20390
21226
|
break;
|
|
20391
21227
|
}
|
|
20392
|
-
if (result4.runtimeProviderFailure) {
|
|
21228
|
+
if (result4.error || result4.runtimeProviderFailure) {
|
|
20393
21229
|
result4 = {
|
|
20394
21230
|
...result4,
|
|
20395
21231
|
error: true,
|
|
20396
|
-
errorMessage: result4.runtimeProviderFailure.
|
|
21232
|
+
errorMessage: result4.runtimeProviderFailure?.message ?? result4.errorMessage
|
|
20397
21233
|
};
|
|
20398
21234
|
break;
|
|
20399
21235
|
}
|
|
@@ -20456,13 +21292,14 @@ ${reasoningTailLog}
|
|
|
20456
21292
|
...result4.reasoning_content ? { reasoning_content: result4.reasoning_content } : {}
|
|
20457
21293
|
};
|
|
20458
21294
|
transcript.push(assistantMessage);
|
|
20459
|
-
if (applyPendingInjections()) {
|
|
21295
|
+
if (await applyPendingInjections()) {
|
|
20460
21296
|
loopTiming.mark("roundEnd", round);
|
|
20461
21297
|
round += 1;
|
|
20462
21298
|
continue;
|
|
20463
21299
|
}
|
|
20464
21300
|
transcript.popLast();
|
|
20465
21301
|
}
|
|
21302
|
+
stopReason = "done";
|
|
20466
21303
|
break;
|
|
20467
21304
|
}
|
|
20468
21305
|
const outputBlocks = result4.output ?? [];
|
|
@@ -20481,9 +21318,11 @@ ${reasoningTailLog}
|
|
|
20481
21318
|
}
|
|
20482
21319
|
}
|
|
20483
21320
|
if (hasInlineExecutedTools) {
|
|
20484
|
-
for (const blockMsg of blocksToOpenAiMessages(outputBlocks)) {
|
|
21321
|
+
for (const blockMsg of blocksToOpenAiMessages(outputBlocks, input.adapter.workspaceRoot)) {
|
|
20485
21322
|
transcript.pushTool(blockMsg);
|
|
20486
21323
|
}
|
|
21324
|
+
const inlineResults = outputBlocks.flatMap((block) => block.type === "toolCall" && block.result ? [block.result] : []);
|
|
21325
|
+
stopReason = inlineResults.some(isToolExecutionFailure) ? "error" : inlineResults.some(({ metadata }) => metadata?.uiAskChoice === true && metadata.resolved !== true) ? "pending" : "done";
|
|
20487
21326
|
skipFinalAppend = true;
|
|
20488
21327
|
break;
|
|
20489
21328
|
}
|
|
@@ -20500,15 +21339,10 @@ ${reasoningTailLog}
|
|
|
20500
21339
|
const executedToolResults = [];
|
|
20501
21340
|
loopTiming.mark("toolLoopStart", round);
|
|
20502
21341
|
const slotResults = new Array(toolCalls.length);
|
|
20503
|
-
const runSingleTool = async ({ index, toolCall }) => {
|
|
20504
|
-
throwIfAborted(
|
|
20505
|
-
if (!budgetAdmissionGate()) {
|
|
20506
|
-
skippedToolCalls.push(toolCall);
|
|
20507
|
-
return;
|
|
20508
|
-
}
|
|
20509
|
-
subtaskBudgetTracker?.recordToolCallExecuted();
|
|
21342
|
+
const runSingleTool = async ({ index, toolCall }, executionInput = input, isClosed = () => false) => {
|
|
21343
|
+
throwIfAborted(executionInput);
|
|
20510
21344
|
const { toolResult, toolExecMs } = await executeToolCall({
|
|
20511
|
-
input,
|
|
21345
|
+
input: executionInput,
|
|
20512
21346
|
toolCall,
|
|
20513
21347
|
round,
|
|
20514
21348
|
boundary: observationBoundary,
|
|
@@ -20521,12 +21355,12 @@ ${reasoningTailLog}
|
|
|
20521
21355
|
...result4.finish_reason ? { finishReason: result4.finish_reason } : {}
|
|
20522
21356
|
}
|
|
20523
21357
|
});
|
|
21358
|
+
if (isClosed()) return;
|
|
20524
21359
|
slotResults[index] = {
|
|
20525
21360
|
toolName: toolCall.function.name,
|
|
20526
21361
|
toolResult,
|
|
20527
21362
|
toolExecMs
|
|
20528
21363
|
};
|
|
20529
|
-
executedToolNameLog.push(toolCall.function.name);
|
|
20530
21364
|
};
|
|
20531
21365
|
const commitSlot = (i) => {
|
|
20532
21366
|
const toolCall = toolCalls[i];
|
|
@@ -20545,7 +21379,8 @@ ${reasoningTailLog}
|
|
|
20545
21379
|
content: formatToolMessageContent({
|
|
20546
21380
|
toolName,
|
|
20547
21381
|
content: toolResult.content,
|
|
20548
|
-
metadata: observedMetadata
|
|
21382
|
+
metadata: observedMetadata,
|
|
21383
|
+
workspaceRoot: input.adapter.workspaceRoot
|
|
20549
21384
|
}),
|
|
20550
21385
|
tool_call_id: toolCall.id,
|
|
20551
21386
|
toolName,
|
|
@@ -20557,14 +21392,36 @@ ${reasoningTailLog}
|
|
|
20557
21392
|
} } : {}
|
|
20558
21393
|
});
|
|
20559
21394
|
};
|
|
20560
|
-
const skippedToolCalls = [];
|
|
20561
21395
|
const batches = partitionToolCallsIntoBatches(toolCalls);
|
|
20562
21396
|
for (const batch of batches) {
|
|
20563
21397
|
throwIfAborted(input);
|
|
20564
21398
|
let batchError;
|
|
20565
21399
|
try {
|
|
20566
21400
|
if (batch.isConcurrent && batch.calls.length > 1) {
|
|
20567
|
-
|
|
21401
|
+
const controller = new AbortController();
|
|
21402
|
+
const batchInput = {
|
|
21403
|
+
...input,
|
|
21404
|
+
abortSignal: input.abortSignal ? AbortSignal.any([input.abortSignal, controller.signal]) : controller.signal
|
|
21405
|
+
};
|
|
21406
|
+
let closed = false;
|
|
21407
|
+
let failed = false;
|
|
21408
|
+
let firstError;
|
|
21409
|
+
const tasks = batch.calls.map((call) => runAbortableToolTask(
|
|
21410
|
+
batchInput,
|
|
21411
|
+
runSingleTool(call, batchInput, () => closed),
|
|
21412
|
+
call.toolCall.function.name
|
|
21413
|
+
).catch((error) => {
|
|
21414
|
+
if (!failed) {
|
|
21415
|
+
failed = true;
|
|
21416
|
+
firstError = error;
|
|
21417
|
+
closed = true;
|
|
21418
|
+
controller.abort();
|
|
21419
|
+
}
|
|
21420
|
+
throw error;
|
|
21421
|
+
}));
|
|
21422
|
+
await Promise.allSettled(tasks);
|
|
21423
|
+
closed = true;
|
|
21424
|
+
if (failed) throw firstError;
|
|
20568
21425
|
} else {
|
|
20569
21426
|
for (const call of batch.calls) {
|
|
20570
21427
|
await runSingleTool(call);
|
|
@@ -20581,15 +21438,20 @@ ${reasoningTailLog}
|
|
|
20581
21438
|
}
|
|
20582
21439
|
if (batchError) throw batchError;
|
|
20583
21440
|
}
|
|
20584
|
-
|
|
20585
|
-
|
|
20586
|
-
|
|
20587
|
-
|
|
20588
|
-
|
|
20589
|
-
|
|
20590
|
-
|
|
21441
|
+
const handoff = executedToolResults.map(({ content }) => {
|
|
21442
|
+
try {
|
|
21443
|
+
return typeof content === "string" ? JSON.parse(content) : null;
|
|
21444
|
+
} catch {
|
|
21445
|
+
return null;
|
|
21446
|
+
}
|
|
21447
|
+
}).find((value) => value?.handoff && typeof value.content === "string" && value.content.trim());
|
|
21448
|
+
if (handoff) {
|
|
21449
|
+
result4 = { ...result4, content: handoff.content };
|
|
21450
|
+
stopReason = "handoff";
|
|
21451
|
+
break;
|
|
20591
21452
|
}
|
|
20592
|
-
if (
|
|
21453
|
+
if (executedToolResults.some(({ metadata }) => metadata?.uiAskChoice === true && metadata.resolved !== true)) {
|
|
21454
|
+
stopReason = "pending";
|
|
20593
21455
|
break;
|
|
20594
21456
|
}
|
|
20595
21457
|
const toolExecutionGuardVerdict = progressGuard.observeToolExecution(
|
|
@@ -20612,117 +21474,28 @@ ${reasoningTailLog}
|
|
|
20612
21474
|
};
|
|
20613
21475
|
break;
|
|
20614
21476
|
}
|
|
20615
|
-
await compaction.maybeCompactInLoop();
|
|
20616
|
-
if (!budgetAdmissionGate()) {
|
|
20617
|
-
break;
|
|
20618
|
-
}
|
|
20619
21477
|
loopTiming.mark("roundEnd", round);
|
|
20620
21478
|
round += 1;
|
|
20621
21479
|
}
|
|
20622
21480
|
} catch (error) {
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
|
|
20626
|
-
let budgetWrapupFailure;
|
|
20627
|
-
let budgetWrapupSucceeded = false;
|
|
20628
|
-
if (!loopError && finalBudgetExhaustion && subtaskBudgetTracker && finalBudgetExhaustion.limit === "max-tool-calls" && !input.abortSignal?.aborted && subtaskBudgetTracker.elapsedMs() < subtaskBudgetTracker.limits.maxWallClockMs) {
|
|
20629
|
-
const remainingMs = subtaskBudgetTracker.limits.maxWallClockMs - subtaskBudgetTracker.elapsedMs();
|
|
20630
|
-
const timeoutMs = Math.min(3e4, remainingMs);
|
|
20631
|
-
const controller = new AbortController();
|
|
20632
|
-
let rejectCancelled = () => {
|
|
20633
|
-
};
|
|
20634
|
-
const cancelled = new Promise((_, reject) => {
|
|
20635
|
-
rejectCancelled = reject;
|
|
20636
|
-
});
|
|
20637
|
-
const onAbort = () => {
|
|
20638
|
-
controller.abort();
|
|
20639
|
-
rejectCancelled(buildAbortedError());
|
|
20640
|
-
};
|
|
20641
|
-
input.abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
20642
|
-
if (input.abortSignal?.aborted) onAbort();
|
|
20643
|
-
let timer;
|
|
20644
|
-
let wrapRequestStarted = false;
|
|
20645
|
-
let wrapUsageCaptured = false;
|
|
20646
|
-
let wrapOutcomeReceived = false;
|
|
21481
|
+
const toRollback = [...pendingInjectionCommits.splice(0), ...inFlightTransactions];
|
|
21482
|
+
inFlightTransactions = [];
|
|
21483
|
+
let rollbackErr;
|
|
20647
21484
|
try {
|
|
20648
|
-
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
reject(new Error("budget wrap-up timed out"));
|
|
20652
|
-
}, timeoutMs);
|
|
20653
|
-
});
|
|
20654
|
-
const work = async () => {
|
|
20655
|
-
const wrapProvider = await input.adapter.resolveProvider(agentConfig, { toolNames: [], prompt: "", textOnly: true });
|
|
20656
|
-
if (!wrapProvider.textOnly) throw new Error(`host ${input.adapter.host} does not support isolated text-only provider`);
|
|
20657
|
-
if (controller.signal.aborted || input.abortSignal?.aborted || subtaskBudgetTracker.elapsedMs() >= subtaskBudgetTracker.limits.maxWallClockMs) throw new Error("budget wrap-up cancelled or deadline reached");
|
|
20658
|
-
const wrapMessages = [
|
|
20659
|
-
...filterImagePartsFromMessages(prepareMessagesForProviderCall(transcript.working()).messages, supportsImages),
|
|
20660
|
-
{ role: "user", content: "\u5DE5\u5177\u9884\u7B97\u5DF2\u8017\u5C3D\u3002\u4E0D\u8981\u8C03\u7528\u5DE5\u5177\uFF1B\u4EC5\u57FA\u4E8E\u5DF2\u5B8C\u6210\u5185\u5BB9\uFF0C\u7B80\u8FF0\u7ED3\u679C\u3001\u8BC1\u636E\u4E0E\u672A\u5B8C\u6210\u4E8B\u9879\u3002" }
|
|
20661
|
-
];
|
|
20662
|
-
const startedAt = Date.now();
|
|
20663
|
-
const telemetry2 = buildRequestTelemetry({ dialogKey: input.continueDialogId || `budget:${crypto.randomUUID()}`, messages: wrapMessages, toolsHash: safeToolNamesHash([]) });
|
|
20664
|
-
wrapRequestStarted = true;
|
|
20665
|
-
const summary2 = await runCompleteWithTimeout({
|
|
20666
|
-
provider: wrapProvider,
|
|
20667
|
-
messages: wrapMessages,
|
|
20668
|
-
options: { max_tokens: 1024, noRetries: true, timeoutMs, signal: controller.signal, ...input.continueDialogId ? { dialogId: input.continueDialogId } : {} },
|
|
20669
|
-
timeoutMs,
|
|
20670
|
-
round,
|
|
20671
|
-
input,
|
|
20672
|
-
boundary: observationBoundary,
|
|
20673
|
-
providerName: agentConfig.provider,
|
|
20674
|
-
model: wrapProvider.model
|
|
20675
|
-
});
|
|
20676
|
-
return { summary: summary2, telemetry: finalizeCallTelemetry(telemetry2, summary2, round, startedAt) };
|
|
20677
|
-
};
|
|
20678
|
-
const { summary, telemetry } = await Promise.race([work(), deadline, cancelled]);
|
|
20679
|
-
wrapOutcomeReceived = true;
|
|
20680
|
-
usageLedger.recordProviderCall({ usage: summary.usage, model: summary.model, provider: summary.provider, telemetry });
|
|
20681
|
-
wrapUsageCaptured = Boolean(summary.usage);
|
|
20682
|
-
if (summary.tool_calls?.length || summary.output?.some((block) => block.type === "toolCall")) throw new Error("text-only provider returned a tool call");
|
|
20683
|
-
if (summary.error || typeof summary.content !== "string" || !summary.content.trim()) throw new Error("text-only provider returned no usable summary");
|
|
20684
|
-
if (input.abortSignal?.aborted) throw buildAbortedError();
|
|
20685
|
-
result4 = { ...result4, content: summary.content.trim().slice(0, 12e3) };
|
|
20686
|
-
budgetWrapupSucceeded = true;
|
|
20687
|
-
} catch (error) {
|
|
20688
|
-
if (input.abortSignal?.aborted) {
|
|
20689
|
-
const aborted = buildAbortedError();
|
|
20690
|
-
if (wrapRequestStarted && !wrapUsageCaptured) {
|
|
20691
|
-
aborted.message += "\uFF08\u65E0\u5DE5\u5177\u603B\u7ED3\u8BF7\u6C42\u53EF\u80FD\u5DF2\u8BA1\u8D39\uFF0C\u672A\u8FD4\u56DE\u7684\u7528\u91CF\u672A\u77E5\uFF09";
|
|
20692
|
-
aborted.usageUnavailable = true;
|
|
20693
|
-
}
|
|
20694
|
-
loopError = aborted;
|
|
20695
|
-
} else {
|
|
20696
|
-
const detail = error instanceof Error ? error.message : "unknown error";
|
|
20697
|
-
budgetWrapupFailure = scrubSecrets(detail).cleaned.slice(0, 300);
|
|
20698
|
-
if (wrapRequestStarted && !wrapOutcomeReceived) budgetWrapupFailure += "\uFF1B\u8BF7\u6C42\u53EF\u80FD\u5DF2\u8BA1\u8D39\uFF0C\u672A\u8FD4\u56DE\u7684\u7528\u91CF\u672A\u77E5";
|
|
20699
|
-
}
|
|
20700
|
-
} finally {
|
|
20701
|
-
if (timer) clearTimeout(timer);
|
|
20702
|
-
controller.abort();
|
|
20703
|
-
input.abortSignal?.removeEventListener("abort", onAbort);
|
|
21485
|
+
await rollbackInjectionCommits(toRollback);
|
|
21486
|
+
} catch (rbErr) {
|
|
21487
|
+
rollbackErr = rbErr;
|
|
20704
21488
|
}
|
|
21489
|
+
loopError = rollbackErr ? combineRollbackError(error, rollbackErr) : error;
|
|
20705
21490
|
}
|
|
20706
21491
|
if (!loopError && input.abortSignal?.aborted) loopError = buildAbortedError();
|
|
20707
|
-
if (budgetExhaustion) {
|
|
20708
|
-
if (!budgetWrapupSucceeded && !budgetWrapupFailure) {
|
|
20709
|
-
budgetWrapupFailure = input.abortSignal?.aborted ? "\u7528\u6237\u5DF2\u53D6\u6D88" : "\u5899\u949F\u9884\u7B97\u5DF2\u8017\u5C3D\uFF0C\u672A\u53D1\u8D77\u603B\u7ED3\u8BF7\u6C42";
|
|
20710
|
-
}
|
|
20711
|
-
const previousContent = typeof result4?.content === "string" ? result4.content.trim() : "";
|
|
20712
|
-
result4 = {
|
|
20713
|
-
...result4,
|
|
20714
|
-
content: [
|
|
20715
|
-
previousContent,
|
|
20716
|
-
...budgetWrapupFailure ? [`\u65E0\u5DE5\u5177\u603B\u7ED3\u672A\u5B8C\u6210\uFF08${budgetWrapupFailure}\uFF09\uFF1B\u4EE5\u4E0B\u662F\u4FDD\u7559\u7684\u5DF2\u6709\u5185\u5BB9\u548C\u9884\u7B97\u72B6\u6001\u3002`] : [],
|
|
20717
|
-
buildSubtaskBudgetExhaustedContent({
|
|
20718
|
-
exhaustion: budgetExhaustion,
|
|
20719
|
-
roundsCompleted: round,
|
|
20720
|
-
recentToolNames: executedToolNameLog
|
|
20721
|
-
})
|
|
20722
|
-
].filter((part) => part.length > 0).join("\n\n")
|
|
20723
|
-
};
|
|
20724
|
-
}
|
|
20725
21492
|
if (loopError) {
|
|
21493
|
+
if (loopError instanceof LocalContextCoverageError && round === 0 && !consumedInjectedMessages) {
|
|
21494
|
+
if (input.continueDialogId) attachDialogIdToError(loopError, input.continueDialogId);
|
|
21495
|
+
attachUsageRecordsToError(loopError, usageLedger.records());
|
|
21496
|
+
await loopTiming.flush();
|
|
21497
|
+
throw loopError;
|
|
21498
|
+
}
|
|
20726
21499
|
const turnMessages2 = transcript.persisted(
|
|
20727
21500
|
sanitizedPersistedInput,
|
|
20728
21501
|
input.persistedInputReference
|
|
@@ -20748,6 +21521,16 @@ ${reasoningTailLog}
|
|
|
20748
21521
|
throw loopError;
|
|
20749
21522
|
}
|
|
20750
21523
|
result4 = result4;
|
|
21524
|
+
result4 = {
|
|
21525
|
+
...result4,
|
|
21526
|
+
stopReason: input.abortSignal?.aborted ? "aborted" : result4.error || result4.runtimeProviderFailure || result4.emptyAssistantFallbackReason ? "error" : stopReason
|
|
21527
|
+
};
|
|
21528
|
+
delete result4.businessCompletion;
|
|
21529
|
+
const businessCompletion = evaluateTaskExecutionContract(input.taskExecutionContract, {
|
|
21530
|
+
stopped: input.abortSignal?.aborted,
|
|
21531
|
+
executionFailed: result4.error === true || !!result4.runtimeProviderFailure || !!result4.emptyAssistantFallbackReason
|
|
21532
|
+
});
|
|
21533
|
+
if (businessCompletion) result4.businessCompletion = businessCompletion;
|
|
20751
21534
|
if (!skipFinalAppend) {
|
|
20752
21535
|
const truncatedReasoningTailLog = resolveTruncatedReasoningTailLog(
|
|
20753
21536
|
result4.emptyAssistantFallbackReason,
|
|
@@ -20834,6 +21617,231 @@ function buildResponsesRequestBody(body, model, options) {
|
|
|
20834
21617
|
};
|
|
20835
21618
|
}
|
|
20836
21619
|
|
|
21620
|
+
// packages/agent-runtime/responsesProtocolLeakSanitizer.ts
|
|
21621
|
+
var LEAKED_PROTOCOL_NOTICE = "\n\n[\u63D0\u793A\uFF1A\u5DF2\u62E6\u622A\u6A21\u578B\u751F\u6210\u7684\u672A\u6267\u884C\u5DE5\u5177\u534F\u8BAE\u7247\u6BB5]";
|
|
21622
|
+
var INLINE_MARKER_REGEXES = [
|
|
21623
|
+
/\u3011\u3010\u3002\s*assistant\s+to\s*=\s*functions\./i,
|
|
21624
|
+
/\u3011\u3010\u3002\s*functions\./i,
|
|
21625
|
+
/<\|(?:im_start|start_header_id)\|>\s*assistant\s+to\s*=\s*functions\./i,
|
|
21626
|
+
/<\|(?:im_start|start_header_id)\|>\s*functions\./i
|
|
21627
|
+
];
|
|
21628
|
+
var INLINE_MARKER_PREFIXES = [
|
|
21629
|
+
"\u3011\u3010\u3002assistant to=functions.",
|
|
21630
|
+
"\u3011\u3010\u3002functions.",
|
|
21631
|
+
"<|im_start|>assistant to=functions.",
|
|
21632
|
+
"<|im_start|>functions.",
|
|
21633
|
+
"<|start_header_id|>assistant to=functions.",
|
|
21634
|
+
"<|start_header_id|>functions."
|
|
21635
|
+
];
|
|
21636
|
+
var TAB_D_PREFIX = " Dfunctions.".toLowerCase();
|
|
21637
|
+
function findLeakedMarker(text2, wasAtLineStart) {
|
|
21638
|
+
let earliestIndex = -1;
|
|
21639
|
+
let earliestLength = 0;
|
|
21640
|
+
for (const regex of INLINE_MARKER_REGEXES) {
|
|
21641
|
+
const match7 = regex.exec(text2);
|
|
21642
|
+
if (match7 && match7.index !== void 0) {
|
|
21643
|
+
if (earliestIndex === -1 || match7.index < earliestIndex) {
|
|
21644
|
+
earliestIndex = match7.index;
|
|
21645
|
+
earliestLength = match7[0].length;
|
|
21646
|
+
}
|
|
21647
|
+
}
|
|
21648
|
+
}
|
|
21649
|
+
const lineMarkerRegex = /(?:^|[\r\n])[ \t]*\tDfunctions\./gi;
|
|
21650
|
+
let m;
|
|
21651
|
+
while ((m = lineMarkerRegex.exec(text2)) !== null) {
|
|
21652
|
+
const isNewline = m[0].startsWith("\n") || m[0].startsWith("\r");
|
|
21653
|
+
const actualIndex = m.index + (isNewline ? 1 : 0);
|
|
21654
|
+
if (actualIndex === 0 && !wasAtLineStart) {
|
|
21655
|
+
continue;
|
|
21656
|
+
}
|
|
21657
|
+
if (earliestIndex === -1 || actualIndex < earliestIndex) {
|
|
21658
|
+
earliestIndex = actualIndex;
|
|
21659
|
+
earliestLength = m[0].length - (isNewline ? 1 : 0);
|
|
21660
|
+
}
|
|
21661
|
+
break;
|
|
21662
|
+
}
|
|
21663
|
+
return earliestIndex >= 0 ? { index: earliestIndex, length: earliestLength } : null;
|
|
21664
|
+
}
|
|
21665
|
+
function calculateHoldLength(buffer3, wasAtLineStart) {
|
|
21666
|
+
let hold = 0;
|
|
21667
|
+
const lower = buffer3.toLowerCase();
|
|
21668
|
+
for (const prefix of INLINE_MARKER_PREFIXES) {
|
|
21669
|
+
const pLower = prefix.toLowerCase();
|
|
21670
|
+
const limit = Math.min(lower.length, pLower.length);
|
|
21671
|
+
for (let len = limit; len > 0; len--) {
|
|
21672
|
+
if (pLower.startsWith(lower.slice(-len))) {
|
|
21673
|
+
if (len > hold) hold = len;
|
|
21674
|
+
break;
|
|
21675
|
+
}
|
|
21676
|
+
}
|
|
21677
|
+
}
|
|
21678
|
+
const trailingLineMatch = /(?:^|[\r\n])[ \t]*$/.exec(buffer3);
|
|
21679
|
+
if (trailingLineMatch) {
|
|
21680
|
+
const isNewline = trailingLineMatch[0].startsWith("\n") || trailingLineMatch[0].startsWith("\r");
|
|
21681
|
+
const len = trailingLineMatch[0].length - (isNewline ? 1 : 0);
|
|
21682
|
+
if (len > 0 && (isNewline || wasAtLineStart)) {
|
|
21683
|
+
if (len > hold) hold = len;
|
|
21684
|
+
}
|
|
21685
|
+
}
|
|
21686
|
+
const trailingTabMatch = /(?:^|[\r\n])[ \t]*(\t[a-zA-Z0-9_\.]*)$/i.exec(lower);
|
|
21687
|
+
if (trailingTabMatch) {
|
|
21688
|
+
const candidate = trailingTabMatch[1];
|
|
21689
|
+
if (TAB_D_PREFIX.startsWith(candidate)) {
|
|
21690
|
+
const isNewline = trailingTabMatch[0].startsWith("\n") || trailingTabMatch[0].startsWith("\r");
|
|
21691
|
+
const len = trailingTabMatch[0].length - (isNewline ? 1 : 0);
|
|
21692
|
+
if (isNewline || wasAtLineStart) {
|
|
21693
|
+
if (len > hold) hold = len;
|
|
21694
|
+
}
|
|
21695
|
+
}
|
|
21696
|
+
}
|
|
21697
|
+
const trailingFenceMatch = /(?:^|[\r\n])[ ]{0,3}(?:`{1,2}|~{1,2})$/.exec(buffer3);
|
|
21698
|
+
if (trailingFenceMatch) {
|
|
21699
|
+
const isNewline = trailingFenceMatch[0].startsWith("\n") || trailingFenceMatch[0].startsWith("\r");
|
|
21700
|
+
const len = trailingFenceMatch[0].length - (isNewline ? 1 : 0);
|
|
21701
|
+
if (isNewline || wasAtLineStart) {
|
|
21702
|
+
if (len > hold) hold = len;
|
|
21703
|
+
}
|
|
21704
|
+
}
|
|
21705
|
+
return hold;
|
|
21706
|
+
}
|
|
21707
|
+
function createResponsesProtocolLeakSanitizer(onTextDelta) {
|
|
21708
|
+
let safeContent = "";
|
|
21709
|
+
let buffer3 = "";
|
|
21710
|
+
let inCodeFence = false;
|
|
21711
|
+
let fenceChar = "";
|
|
21712
|
+
let fenceLength = 0;
|
|
21713
|
+
let intercepted = false;
|
|
21714
|
+
let wasAtLineStart = true;
|
|
21715
|
+
const emit = (text2) => {
|
|
21716
|
+
safeContent += text2;
|
|
21717
|
+
onTextDelta?.(text2);
|
|
21718
|
+
if (text2.length > 0) {
|
|
21719
|
+
const last = text2[text2.length - 1];
|
|
21720
|
+
wasAtLineStart = last === "\n" || last === "\r";
|
|
21721
|
+
}
|
|
21722
|
+
};
|
|
21723
|
+
const processBuffer = (isFinal) => {
|
|
21724
|
+
if (intercepted) return;
|
|
21725
|
+
while (buffer3.length > 0) {
|
|
21726
|
+
if (!inCodeFence) {
|
|
21727
|
+
let fenceIndex = -1;
|
|
21728
|
+
let fenceMarkerStr = "";
|
|
21729
|
+
let lineStartOffset = 0;
|
|
21730
|
+
const fenceRegex = /(?:^|[\r\n])[ ]{0,3}(`{3,}|~{3,})[^\r\n]*(?:\r?\n|$)/g;
|
|
21731
|
+
let m;
|
|
21732
|
+
while ((m = fenceRegex.exec(buffer3)) !== null) {
|
|
21733
|
+
const isNewlinePreceded = m[0].startsWith("\n") || m[0].startsWith("\r");
|
|
21734
|
+
const actualStart = m.index + (isNewlinePreceded ? 1 : 0);
|
|
21735
|
+
if (actualStart === 0 && !wasAtLineStart) {
|
|
21736
|
+
continue;
|
|
21737
|
+
}
|
|
21738
|
+
fenceIndex = actualStart;
|
|
21739
|
+
fenceMarkerStr = m[1];
|
|
21740
|
+
lineStartOffset = m[0].length - (isNewlinePreceded ? 1 : 0);
|
|
21741
|
+
break;
|
|
21742
|
+
}
|
|
21743
|
+
const markerMatch = findLeakedMarker(buffer3, wasAtLineStart);
|
|
21744
|
+
const markerIndex = markerMatch ? markerMatch.index : -1;
|
|
21745
|
+
if (markerIndex >= 0 && (fenceIndex === -1 || markerIndex < fenceIndex)) {
|
|
21746
|
+
const normalPart = buffer3.slice(0, markerIndex);
|
|
21747
|
+
emit(normalPart);
|
|
21748
|
+
emit(LEAKED_PROTOCOL_NOTICE);
|
|
21749
|
+
intercepted = true;
|
|
21750
|
+
buffer3 = "";
|
|
21751
|
+
return;
|
|
21752
|
+
}
|
|
21753
|
+
if (fenceIndex >= 0) {
|
|
21754
|
+
if (!isFinal && !buffer3.slice(fenceIndex).includes("\n") && !buffer3.slice(fenceIndex).includes("\r")) {
|
|
21755
|
+
const beforeFence2 = buffer3.slice(0, fenceIndex);
|
|
21756
|
+
emit(beforeFence2);
|
|
21757
|
+
buffer3 = buffer3.slice(fenceIndex);
|
|
21758
|
+
return;
|
|
21759
|
+
}
|
|
21760
|
+
const beforeFence = buffer3.slice(0, fenceIndex);
|
|
21761
|
+
emit(beforeFence);
|
|
21762
|
+
inCodeFence = true;
|
|
21763
|
+
fenceChar = fenceMarkerStr[0];
|
|
21764
|
+
fenceLength = fenceMarkerStr.length;
|
|
21765
|
+
emit(buffer3.slice(fenceIndex, fenceIndex + lineStartOffset));
|
|
21766
|
+
buffer3 = buffer3.slice(fenceIndex + lineStartOffset);
|
|
21767
|
+
continue;
|
|
21768
|
+
}
|
|
21769
|
+
if (isFinal) {
|
|
21770
|
+
emit(buffer3);
|
|
21771
|
+
buffer3 = "";
|
|
21772
|
+
return;
|
|
21773
|
+
}
|
|
21774
|
+
const hold = calculateHoldLength(buffer3, wasAtLineStart);
|
|
21775
|
+
if (hold === 0) {
|
|
21776
|
+
emit(buffer3);
|
|
21777
|
+
buffer3 = "";
|
|
21778
|
+
} else if (hold < buffer3.length) {
|
|
21779
|
+
emit(buffer3.slice(0, buffer3.length - hold));
|
|
21780
|
+
buffer3 = buffer3.slice(buffer3.length - hold);
|
|
21781
|
+
}
|
|
21782
|
+
return;
|
|
21783
|
+
} else {
|
|
21784
|
+
const closeRegex = new RegExp(`(?:^|[\\r\\n])[ ]{0,3}${fenceChar}{${fenceLength},}[ ]*(?:\\r?\\n|$)`, "g");
|
|
21785
|
+
const closeMatch = closeRegex.exec(buffer3);
|
|
21786
|
+
if (closeMatch) {
|
|
21787
|
+
const isNewlinePreceded = closeMatch[0].startsWith("\n") || closeMatch[0].startsWith("\r");
|
|
21788
|
+
const actualStart = closeMatch.index + (isNewlinePreceded ? 1 : 0);
|
|
21789
|
+
if (actualStart === 0 && !wasAtLineStart) {
|
|
21790
|
+
emit(buffer3.slice(0, closeMatch.index + 1));
|
|
21791
|
+
buffer3 = buffer3.slice(closeMatch.index + 1);
|
|
21792
|
+
continue;
|
|
21793
|
+
}
|
|
21794
|
+
const closeEnd = closeMatch.index + closeMatch[0].length;
|
|
21795
|
+
emit(buffer3.slice(0, closeEnd));
|
|
21796
|
+
buffer3 = buffer3.slice(closeEnd);
|
|
21797
|
+
inCodeFence = false;
|
|
21798
|
+
fenceChar = "";
|
|
21799
|
+
fenceLength = 0;
|
|
21800
|
+
continue;
|
|
21801
|
+
}
|
|
21802
|
+
if (isFinal) {
|
|
21803
|
+
emit(buffer3);
|
|
21804
|
+
buffer3 = "";
|
|
21805
|
+
return;
|
|
21806
|
+
}
|
|
21807
|
+
const trailingCloseMatch = new RegExp(`(?:^|[\\r\\n])[ ]{0,3}${fenceChar}{1,${fenceLength}}$`).exec(buffer3);
|
|
21808
|
+
const hold = trailingCloseMatch ? trailingCloseMatch[0].length : 0;
|
|
21809
|
+
if (hold === 0) {
|
|
21810
|
+
emit(buffer3);
|
|
21811
|
+
buffer3 = "";
|
|
21812
|
+
} else if (hold < buffer3.length) {
|
|
21813
|
+
emit(buffer3.slice(0, buffer3.length - hold));
|
|
21814
|
+
buffer3 = buffer3.slice(buffer3.length - hold);
|
|
21815
|
+
}
|
|
21816
|
+
return;
|
|
21817
|
+
}
|
|
21818
|
+
}
|
|
21819
|
+
};
|
|
21820
|
+
return {
|
|
21821
|
+
push(chunk) {
|
|
21822
|
+
if (intercepted) return;
|
|
21823
|
+
if (chunk.length === 0) {
|
|
21824
|
+
emit("");
|
|
21825
|
+
return;
|
|
21826
|
+
}
|
|
21827
|
+
buffer3 += chunk;
|
|
21828
|
+
processBuffer(false);
|
|
21829
|
+
},
|
|
21830
|
+
finalize() {
|
|
21831
|
+
processBuffer(true);
|
|
21832
|
+
return {
|
|
21833
|
+
content: safeContent,
|
|
21834
|
+
intercepted
|
|
21835
|
+
};
|
|
21836
|
+
}
|
|
21837
|
+
};
|
|
21838
|
+
}
|
|
21839
|
+
function sanitizeResponsesProtocolLeakText(text2) {
|
|
21840
|
+
const sanitizer = createResponsesProtocolLeakSanitizer();
|
|
21841
|
+
sanitizer.push(text2);
|
|
21842
|
+
return sanitizer.finalize();
|
|
21843
|
+
}
|
|
21844
|
+
|
|
20837
21845
|
// packages/agent-runtime/responsesSseStream.ts
|
|
20838
21846
|
function toResponsesStreamFailure(raw, fallbackPrefix = "Responses") {
|
|
20839
21847
|
if (!raw || typeof raw !== "object") return void 0;
|
|
@@ -20870,6 +21878,8 @@ function hasNumericTokenCount(u) {
|
|
|
20870
21878
|
function createResponsesStreamCollector(callbacks) {
|
|
20871
21879
|
let content = "";
|
|
20872
21880
|
let reasoning = "";
|
|
21881
|
+
const textSanitizer = createResponsesProtocolLeakSanitizer(callbacks?.onTextDelta);
|
|
21882
|
+
let sawNonEmptyOutputTextDelta = false;
|
|
20873
21883
|
const toolCallsAcc = createResponsesToolAccumulator();
|
|
20874
21884
|
let usage;
|
|
20875
21885
|
let failure;
|
|
@@ -20921,8 +21931,8 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
20921
21931
|
return;
|
|
20922
21932
|
}
|
|
20923
21933
|
if (type === "response.output_text.delta" && typeof ev.delta === "string") {
|
|
20924
|
-
|
|
20925
|
-
|
|
21934
|
+
if (ev.delta.length > 0) sawNonEmptyOutputTextDelta = true;
|
|
21935
|
+
textSanitizer.push(ev.delta);
|
|
20926
21936
|
return;
|
|
20927
21937
|
}
|
|
20928
21938
|
if ((type === "response.reasoning_text.delta" || type === "response.reasoning.delta") && typeof ev.delta === "string") {
|
|
@@ -20932,11 +21942,11 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
20932
21942
|
}
|
|
20933
21943
|
if (type === "response.output_item.added" || type === "response.output_item.done") {
|
|
20934
21944
|
const item = ev.item;
|
|
20935
|
-
if (item?.type === "message" && !
|
|
21945
|
+
if (item?.type === "message" && !sawNonEmptyOutputTextDelta) {
|
|
20936
21946
|
const itemText = extractOutputTextFromItem(item);
|
|
20937
21947
|
if (itemText) {
|
|
20938
|
-
|
|
20939
|
-
|
|
21948
|
+
sawNonEmptyOutputTextDelta = true;
|
|
21949
|
+
textSanitizer.push(itemText);
|
|
20940
21950
|
}
|
|
20941
21951
|
}
|
|
20942
21952
|
applyResponsesToolEvent(toolCallsAcc, ev);
|
|
@@ -21035,8 +22045,16 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
21035
22045
|
if (authoritativeCompletedTools && failure) {
|
|
21036
22046
|
finalToolCalls = [];
|
|
21037
22047
|
}
|
|
22048
|
+
const sanitized = textSanitizer.finalize();
|
|
22049
|
+
content = sanitized.content;
|
|
22050
|
+
let intercepted = sanitized.intercepted;
|
|
21038
22051
|
if (!content && completedResponse) {
|
|
21039
|
-
|
|
22052
|
+
const extracted = extractTextFromResponseOutput(completedResponse);
|
|
22053
|
+
if (extracted) {
|
|
22054
|
+
const sanitizedExtracted = sanitizeResponsesProtocolLeakText(extracted);
|
|
22055
|
+
content = sanitizedExtracted.content;
|
|
22056
|
+
if (sanitizedExtracted.intercepted) intercepted = true;
|
|
22057
|
+
}
|
|
21040
22058
|
}
|
|
21041
22059
|
if (!reasoning && completedResponse) {
|
|
21042
22060
|
reasoning = extractReasoningFromResponseOutput(completedResponse);
|
|
@@ -21051,6 +22069,7 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
21051
22069
|
...streamComplete ? { finish_reason: finalToolCalls.length > 0 ? "tool_calls" : "stop" } : {},
|
|
21052
22070
|
...streamComplete ? { stream_complete: true } : {},
|
|
21053
22071
|
...streamTruncated ? { stream_truncated: true } : {},
|
|
22072
|
+
...intercepted ? { leaked_protocol_intercepted: true } : {},
|
|
21054
22073
|
...completedResponse ? { completed_response: completedResponse } : {},
|
|
21055
22074
|
...completedResponse && typeof completedResponse.id === "string" ? { response_id: completedResponse.id } : {},
|
|
21056
22075
|
...failure ? { failure } : {}
|
|
@@ -21432,6 +22451,7 @@ async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
|
21432
22451
|
...streamed2.usage ? { usage: streamed2.usage } : {},
|
|
21433
22452
|
...streamed2.stream_complete ? { stream_complete: true } : {},
|
|
21434
22453
|
...streamed2.finish_reason ? { finish_reason: streamed2.finish_reason } : {},
|
|
22454
|
+
...streamed2.leaked_protocol_intercepted ? { leaked_protocol_intercepted: true } : {},
|
|
21435
22455
|
trace: args2.messages
|
|
21436
22456
|
});
|
|
21437
22457
|
}
|
|
@@ -21479,6 +22499,16 @@ async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
|
21479
22499
|
throw error;
|
|
21480
22500
|
}
|
|
21481
22501
|
}
|
|
22502
|
+
function describeOpenAiCompatibleRequestBudget(args2) {
|
|
22503
|
+
const request3 = buildOpenAiCompatibleChatCompletionRequest({ ...args2, messages: [] });
|
|
22504
|
+
const body = JSON.parse(request3.init.body);
|
|
22505
|
+
const cap = body.max_completion_tokens ?? body.max_output_tokens ?? body.max_tokens;
|
|
22506
|
+
return {
|
|
22507
|
+
toolSchemaTokens: estimateTokenCount(JSON.stringify(body.tools ?? [])),
|
|
22508
|
+
// Explicit wire allowance is conservatively reserved. Omitted provider defaults are unknown.
|
|
22509
|
+
output: typeof cap === "number" && Number.isFinite(cap) && cap > 0 ? { semantics: "shared-window", finalWireCapTokens: cap } : { semantics: "unknown", fallbackReserveTokens: 8192 }
|
|
22510
|
+
};
|
|
22511
|
+
}
|
|
21482
22512
|
|
|
21483
22513
|
// packages/agent-runtime/openAiCompatibleProviderConfig.ts
|
|
21484
22514
|
async function resolveOpenAiCompatibleProviderConfig(args2) {
|
|
@@ -22622,7 +23652,8 @@ function createHybridRecordStore(deps) {
|
|
|
22622
23652
|
const normalizedLocalRecord = normalizeHybridRecord(dbKey, localRecord);
|
|
22623
23653
|
if (normalizedLocalRecord && options?.remote !== true) return normalizedLocalRecord;
|
|
22624
23654
|
if (options?.remote === false) return null;
|
|
22625
|
-
const
|
|
23655
|
+
const effectiveTimeoutMs = typeof options?.timeoutMs === "number" && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0 ? options.timeoutMs : requestTimeoutMs;
|
|
23656
|
+
const fallbackDeadlineMs = effectiveTimeoutMs > 0 ? Date.now() + effectiveTimeoutMs : null;
|
|
22626
23657
|
for (const server of resolveHybridServers(
|
|
22627
23658
|
deps.defaultServer,
|
|
22628
23659
|
options?.preferredServerOrigin,
|
|
@@ -22673,6 +23704,267 @@ function createHybridRecordStore(deps) {
|
|
|
22673
23704
|
var DEFAULT_SANDBOX_TMPFS_SIZE_BYTES = 128 * 1024 * 1024;
|
|
22674
23705
|
var BWRAP_PROBE_TTL_MS = 5 * 6e4;
|
|
22675
23706
|
|
|
23707
|
+
// node_modules/async-mutex/index.mjs
|
|
23708
|
+
var E_TIMEOUT = new Error("timeout while waiting for mutex to become available");
|
|
23709
|
+
var E_ALREADY_LOCKED = new Error("mutex already locked");
|
|
23710
|
+
var E_CANCELED = new Error("request for lock canceled");
|
|
23711
|
+
var __awaiter$2 = function(thisArg, _arguments, P, generator) {
|
|
23712
|
+
function adopt(value) {
|
|
23713
|
+
return value instanceof P ? value : new P(function(resolve6) {
|
|
23714
|
+
resolve6(value);
|
|
23715
|
+
});
|
|
23716
|
+
}
|
|
23717
|
+
return new (P || (P = Promise))(function(resolve6, reject) {
|
|
23718
|
+
function fulfilled(value) {
|
|
23719
|
+
try {
|
|
23720
|
+
step(generator.next(value));
|
|
23721
|
+
} catch (e) {
|
|
23722
|
+
reject(e);
|
|
23723
|
+
}
|
|
23724
|
+
}
|
|
23725
|
+
function rejected(value) {
|
|
23726
|
+
try {
|
|
23727
|
+
step(generator["throw"](value));
|
|
23728
|
+
} catch (e) {
|
|
23729
|
+
reject(e);
|
|
23730
|
+
}
|
|
23731
|
+
}
|
|
23732
|
+
function step(result4) {
|
|
23733
|
+
result4.done ? resolve6(result4.value) : adopt(result4.value).then(fulfilled, rejected);
|
|
23734
|
+
}
|
|
23735
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23736
|
+
});
|
|
23737
|
+
};
|
|
23738
|
+
var Semaphore = class {
|
|
23739
|
+
constructor(_value, _cancelError = E_CANCELED) {
|
|
23740
|
+
this._value = _value;
|
|
23741
|
+
this._cancelError = _cancelError;
|
|
23742
|
+
this._queue = [];
|
|
23743
|
+
this._weightedWaiters = [];
|
|
23744
|
+
}
|
|
23745
|
+
acquire(weight = 1, priority = 0) {
|
|
23746
|
+
if (weight <= 0)
|
|
23747
|
+
throw new Error(`invalid weight ${weight}: must be positive`);
|
|
23748
|
+
return new Promise((resolve6, reject) => {
|
|
23749
|
+
const task = { resolve: resolve6, reject, weight, priority };
|
|
23750
|
+
const i = findIndexFromEnd(this._queue, (other) => priority <= other.priority);
|
|
23751
|
+
if (i === -1 && weight <= this._value) {
|
|
23752
|
+
this._dispatchItem(task);
|
|
23753
|
+
} else {
|
|
23754
|
+
this._queue.splice(i + 1, 0, task);
|
|
23755
|
+
}
|
|
23756
|
+
});
|
|
23757
|
+
}
|
|
23758
|
+
runExclusive(callback_1) {
|
|
23759
|
+
return __awaiter$2(this, arguments, void 0, function* (callback4, weight = 1, priority = 0) {
|
|
23760
|
+
const [value, release3] = yield this.acquire(weight, priority);
|
|
23761
|
+
try {
|
|
23762
|
+
return yield callback4(value);
|
|
23763
|
+
} finally {
|
|
23764
|
+
release3();
|
|
23765
|
+
}
|
|
23766
|
+
});
|
|
23767
|
+
}
|
|
23768
|
+
waitForUnlock(weight = 1, priority = 0) {
|
|
23769
|
+
if (weight <= 0)
|
|
23770
|
+
throw new Error(`invalid weight ${weight}: must be positive`);
|
|
23771
|
+
if (this._couldLockImmediately(weight, priority)) {
|
|
23772
|
+
return Promise.resolve();
|
|
23773
|
+
} else {
|
|
23774
|
+
return new Promise((resolve6) => {
|
|
23775
|
+
if (!this._weightedWaiters[weight - 1])
|
|
23776
|
+
this._weightedWaiters[weight - 1] = [];
|
|
23777
|
+
insertSorted(this._weightedWaiters[weight - 1], { resolve: resolve6, priority });
|
|
23778
|
+
});
|
|
23779
|
+
}
|
|
23780
|
+
}
|
|
23781
|
+
isLocked() {
|
|
23782
|
+
return this._value <= 0;
|
|
23783
|
+
}
|
|
23784
|
+
getValue() {
|
|
23785
|
+
return this._value;
|
|
23786
|
+
}
|
|
23787
|
+
setValue(value) {
|
|
23788
|
+
this._value = value;
|
|
23789
|
+
this._dispatchQueue();
|
|
23790
|
+
}
|
|
23791
|
+
release(weight = 1) {
|
|
23792
|
+
if (weight <= 0)
|
|
23793
|
+
throw new Error(`invalid weight ${weight}: must be positive`);
|
|
23794
|
+
this._value += weight;
|
|
23795
|
+
this._dispatchQueue();
|
|
23796
|
+
}
|
|
23797
|
+
cancel() {
|
|
23798
|
+
this._queue.forEach((entry) => entry.reject(this._cancelError));
|
|
23799
|
+
this._queue = [];
|
|
23800
|
+
}
|
|
23801
|
+
_dispatchQueue() {
|
|
23802
|
+
this._drainUnlockWaiters();
|
|
23803
|
+
while (this._queue.length > 0 && this._queue[0].weight <= this._value) {
|
|
23804
|
+
this._dispatchItem(this._queue.shift());
|
|
23805
|
+
this._drainUnlockWaiters();
|
|
23806
|
+
}
|
|
23807
|
+
}
|
|
23808
|
+
_dispatchItem(item) {
|
|
23809
|
+
const previousValue = this._value;
|
|
23810
|
+
this._value -= item.weight;
|
|
23811
|
+
item.resolve([previousValue, this._newReleaser(item.weight)]);
|
|
23812
|
+
}
|
|
23813
|
+
_newReleaser(weight) {
|
|
23814
|
+
let called = false;
|
|
23815
|
+
return () => {
|
|
23816
|
+
if (called)
|
|
23817
|
+
return;
|
|
23818
|
+
called = true;
|
|
23819
|
+
this.release(weight);
|
|
23820
|
+
};
|
|
23821
|
+
}
|
|
23822
|
+
_drainUnlockWaiters() {
|
|
23823
|
+
if (this._queue.length === 0) {
|
|
23824
|
+
for (let weight = this._value; weight > 0; weight--) {
|
|
23825
|
+
const waiters = this._weightedWaiters[weight - 1];
|
|
23826
|
+
if (!waiters)
|
|
23827
|
+
continue;
|
|
23828
|
+
waiters.forEach((waiter) => waiter.resolve());
|
|
23829
|
+
this._weightedWaiters[weight - 1] = [];
|
|
23830
|
+
}
|
|
23831
|
+
} else {
|
|
23832
|
+
const queuedPriority = this._queue[0].priority;
|
|
23833
|
+
for (let weight = this._value; weight > 0; weight--) {
|
|
23834
|
+
const waiters = this._weightedWaiters[weight - 1];
|
|
23835
|
+
if (!waiters)
|
|
23836
|
+
continue;
|
|
23837
|
+
const i = waiters.findIndex((waiter) => waiter.priority <= queuedPriority);
|
|
23838
|
+
(i === -1 ? waiters : waiters.splice(0, i)).forEach((waiter) => waiter.resolve());
|
|
23839
|
+
}
|
|
23840
|
+
}
|
|
23841
|
+
}
|
|
23842
|
+
_couldLockImmediately(weight, priority) {
|
|
23843
|
+
return (this._queue.length === 0 || this._queue[0].priority < priority) && weight <= this._value;
|
|
23844
|
+
}
|
|
23845
|
+
};
|
|
23846
|
+
function insertSorted(a, v) {
|
|
23847
|
+
const i = findIndexFromEnd(a, (other) => v.priority <= other.priority);
|
|
23848
|
+
a.splice(i + 1, 0, v);
|
|
23849
|
+
}
|
|
23850
|
+
function findIndexFromEnd(a, predicate) {
|
|
23851
|
+
for (let i = a.length - 1; i >= 0; i--) {
|
|
23852
|
+
if (predicate(a[i])) {
|
|
23853
|
+
return i;
|
|
23854
|
+
}
|
|
23855
|
+
}
|
|
23856
|
+
return -1;
|
|
23857
|
+
}
|
|
23858
|
+
var __awaiter$1 = function(thisArg, _arguments, P, generator) {
|
|
23859
|
+
function adopt(value) {
|
|
23860
|
+
return value instanceof P ? value : new P(function(resolve6) {
|
|
23861
|
+
resolve6(value);
|
|
23862
|
+
});
|
|
23863
|
+
}
|
|
23864
|
+
return new (P || (P = Promise))(function(resolve6, reject) {
|
|
23865
|
+
function fulfilled(value) {
|
|
23866
|
+
try {
|
|
23867
|
+
step(generator.next(value));
|
|
23868
|
+
} catch (e) {
|
|
23869
|
+
reject(e);
|
|
23870
|
+
}
|
|
23871
|
+
}
|
|
23872
|
+
function rejected(value) {
|
|
23873
|
+
try {
|
|
23874
|
+
step(generator["throw"](value));
|
|
23875
|
+
} catch (e) {
|
|
23876
|
+
reject(e);
|
|
23877
|
+
}
|
|
23878
|
+
}
|
|
23879
|
+
function step(result4) {
|
|
23880
|
+
result4.done ? resolve6(result4.value) : adopt(result4.value).then(fulfilled, rejected);
|
|
23881
|
+
}
|
|
23882
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23883
|
+
});
|
|
23884
|
+
};
|
|
23885
|
+
var Mutex = class {
|
|
23886
|
+
constructor(cancelError) {
|
|
23887
|
+
this._semaphore = new Semaphore(1, cancelError);
|
|
23888
|
+
}
|
|
23889
|
+
acquire() {
|
|
23890
|
+
return __awaiter$1(this, arguments, void 0, function* (priority = 0) {
|
|
23891
|
+
const [, releaser] = yield this._semaphore.acquire(1, priority);
|
|
23892
|
+
return releaser;
|
|
23893
|
+
});
|
|
23894
|
+
}
|
|
23895
|
+
runExclusive(callback4, priority = 0) {
|
|
23896
|
+
return this._semaphore.runExclusive(() => callback4(), 1, priority);
|
|
23897
|
+
}
|
|
23898
|
+
isLocked() {
|
|
23899
|
+
return this._semaphore.isLocked();
|
|
23900
|
+
}
|
|
23901
|
+
waitForUnlock(priority = 0) {
|
|
23902
|
+
return this._semaphore.waitForUnlock(1, priority);
|
|
23903
|
+
}
|
|
23904
|
+
release() {
|
|
23905
|
+
if (this._semaphore.isLocked())
|
|
23906
|
+
this._semaphore.release();
|
|
23907
|
+
}
|
|
23908
|
+
cancel() {
|
|
23909
|
+
return this._semaphore.cancel();
|
|
23910
|
+
}
|
|
23911
|
+
};
|
|
23912
|
+
|
|
23913
|
+
// packages/database-engine/dialogOwner.ts
|
|
23914
|
+
var dialogOwnerKey = (dialogId) => `dialogown-${dialogId}`;
|
|
23915
|
+
var locks = /* @__PURE__ */ new Map();
|
|
23916
|
+
async function registerDialogOwner(args2) {
|
|
23917
|
+
const emit = (event) => {
|
|
23918
|
+
try {
|
|
23919
|
+
(args2.log ?? ((event2) => console.warn(event2)))(event);
|
|
23920
|
+
} catch {
|
|
23921
|
+
}
|
|
23922
|
+
};
|
|
23923
|
+
const key = dialogOwnerKey(args2.dialogId);
|
|
23924
|
+
let mutex = locks.get(key);
|
|
23925
|
+
if (!mutex) {
|
|
23926
|
+
mutex = new Mutex();
|
|
23927
|
+
locks.set(key, mutex);
|
|
23928
|
+
}
|
|
23929
|
+
try {
|
|
23930
|
+
await mutex.runExclusive(async () => {
|
|
23931
|
+
let existing;
|
|
23932
|
+
try {
|
|
23933
|
+
existing = await args2.store.get(key);
|
|
23934
|
+
} catch (error) {
|
|
23935
|
+
if (!isLevelNotFoundError(error)) throw error;
|
|
23936
|
+
existing = null;
|
|
23937
|
+
}
|
|
23938
|
+
if (existing != null) {
|
|
23939
|
+
if (existing.ownerId !== args2.ownerId) emit({
|
|
23940
|
+
event: "dialog_owner_conflict",
|
|
23941
|
+
dialogId: args2.dialogId,
|
|
23942
|
+
existingOwnerId: existing.ownerId,
|
|
23943
|
+
attemptedOwnerId: args2.ownerId,
|
|
23944
|
+
source: args2.source
|
|
23945
|
+
});
|
|
23946
|
+
return;
|
|
23947
|
+
}
|
|
23948
|
+
await args2.store.put(key, {
|
|
23949
|
+
dialogId: args2.dialogId,
|
|
23950
|
+
ownerId: args2.ownerId,
|
|
23951
|
+
...args2.spaceId !== void 0 ? { spaceId: args2.spaceId } : {},
|
|
23952
|
+
source: args2.source,
|
|
23953
|
+
registeredAt: (args2.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))()
|
|
23954
|
+
});
|
|
23955
|
+
});
|
|
23956
|
+
} catch (error) {
|
|
23957
|
+
emit({
|
|
23958
|
+
event: "dialog_owner_registration_failed",
|
|
23959
|
+
dialogId: args2.dialogId,
|
|
23960
|
+
source: args2.source,
|
|
23961
|
+
error: error instanceof Error ? error.message : String(error)
|
|
23962
|
+
});
|
|
23963
|
+
} finally {
|
|
23964
|
+
if (!mutex.isLocked() && locks.get(key) === mutex) locks.delete(key);
|
|
23965
|
+
}
|
|
23966
|
+
}
|
|
23967
|
+
|
|
22676
23968
|
// packages/cli/client/localDialogRecords.ts
|
|
22677
23969
|
var localDialogMessageRecordToRuntimeMessage = dialogMessageRecordToAgentRuntimeMessage;
|
|
22678
23970
|
function buildLocalDialogWritePlan(args2) {
|
|
@@ -22689,6 +23981,138 @@ function buildLocalDialogWritePlan(args2) {
|
|
|
22689
23981
|
...args2.titleOverride ? { titleOverride: args2.titleOverride } : {}
|
|
22690
23982
|
});
|
|
22691
23983
|
}
|
|
23984
|
+
async function saveCliPendingUserMessages(args2) {
|
|
23985
|
+
const dialogKey = `dialog-${args2.userId}-${args2.dialogId}`;
|
|
23986
|
+
const existing = await args2.store.read(dialogKey, { remote: false });
|
|
23987
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23988
|
+
const ops = [];
|
|
23989
|
+
if (!existing) ops.push({ type: "put", key: dialogKey, value: {
|
|
23990
|
+
id: args2.dialogId,
|
|
23991
|
+
dbKey: dialogKey,
|
|
23992
|
+
type: "dialog",
|
|
23993
|
+
userId: args2.userId,
|
|
23994
|
+
primaryAgentKey: args2.agentKey,
|
|
23995
|
+
cybots: [args2.agentKey],
|
|
23996
|
+
createdAt: now,
|
|
23997
|
+
updatedAt: now
|
|
23998
|
+
} });
|
|
23999
|
+
for (const request3 of args2.requests) {
|
|
24000
|
+
if (!request3.messageId) throw new Error("Pending user message requires a stable messageId");
|
|
24001
|
+
const key = `dialog-${args2.dialogId}-msg-${request3.messageId}`;
|
|
24002
|
+
if (await args2.store.read(key, { remote: false })) continue;
|
|
24003
|
+
ops.push({ type: "put", key, value: {
|
|
24004
|
+
id: request3.messageId,
|
|
24005
|
+
dbKey: key,
|
|
24006
|
+
type: "message",
|
|
24007
|
+
dialogId: args2.dialogId,
|
|
24008
|
+
userId: args2.userId,
|
|
24009
|
+
role: "user",
|
|
24010
|
+
content: request3.text,
|
|
24011
|
+
createdAt: now,
|
|
24012
|
+
metadata: {
|
|
24013
|
+
queueState: "pending",
|
|
24014
|
+
source: request3.source ?? "tui",
|
|
24015
|
+
imagePaths: request3.imagePaths,
|
|
24016
|
+
mediaPaths: request3.mediaPaths
|
|
24017
|
+
}
|
|
24018
|
+
} });
|
|
24019
|
+
}
|
|
24020
|
+
await registerDialogOwner({
|
|
24021
|
+
store: { get: (key) => args2.store.read(key, { remote: false }), put: (key, value) => args2.store.batch([{ type: "put", key, value }]) },
|
|
24022
|
+
dialogId: args2.dialogId,
|
|
24023
|
+
ownerId: args2.userId,
|
|
24024
|
+
source: "cli-pending-user"
|
|
24025
|
+
});
|
|
24026
|
+
if (ops.length) await args2.store.batch(ops);
|
|
24027
|
+
}
|
|
24028
|
+
async function readCliPendingUserMessages(store, dialogId) {
|
|
24029
|
+
const { readDialogMessageRecords } = await import("./cliLocalAgentRecordReader-MHHD4T7R.js");
|
|
24030
|
+
const rows = await readDialogMessageRecords({ store, dialogId });
|
|
24031
|
+
const uncertain = rows.filter(({ record: record2 }) => record2.metadata?.cliBatchPhase === "requested" && !record2.metadata?.cliBatchResolution);
|
|
24032
|
+
const recovery = uncertain.length ? {
|
|
24033
|
+
status: "unknown",
|
|
24034
|
+
messageIds: uncertain.map((row) => row.messageId),
|
|
24035
|
+
// Attribute each unknown batch to its own members via the tail receipt.
|
|
24036
|
+
// `acceptedUserMessageIds` is written by `markCliUserBatchPhase`; older
|
|
24037
|
+
// records carry the same field from the legacy admission path. Records with
|
|
24038
|
+
// neither fall back to every accepted row (never attribute a completed
|
|
24039
|
+
// batch's members to an unknown one when the receipt is available).
|
|
24040
|
+
batches: uncertain.map((row) => {
|
|
24041
|
+
const receiptIds = row.record.metadata?.acceptedUserMessageIds;
|
|
24042
|
+
const memberIds = Array.isArray(receiptIds) && receiptIds.length ? receiptIds : rows.filter((message) => message.record.metadata?.queueState === "accepted").map((message) => message.messageId);
|
|
24043
|
+
const memberSet = new Set(memberIds);
|
|
24044
|
+
return { batchId: row.messageId, messages: rows.filter((message) => memberSet.has(message.messageId)).map((message) => ({ messageId: message.messageId, text: String(message.record.content ?? "") })) };
|
|
24045
|
+
}),
|
|
24046
|
+
message: `Batch provider outcome unknown for ${uncertain.map((row) => row.messageId).join(", ")}; pending history retained; resubmission paused to avoid duplicate billing`
|
|
24047
|
+
} : { status: "ready", messageIds: [] };
|
|
24048
|
+
const pending = rows.filter(({ record: record2 }) => record2.role === "user" && record2.metadata?.queueState === "pending").map(({ record: record2, messageId }) => ({
|
|
24049
|
+
messageId,
|
|
24050
|
+
source: record2.metadata?.source,
|
|
24051
|
+
text: String(record2.content ?? ""),
|
|
24052
|
+
event: { kind: "user", text: String(record2.content ?? "") },
|
|
24053
|
+
imagePaths: record2.metadata?.imagePaths,
|
|
24054
|
+
mediaPaths: record2.metadata?.mediaPaths
|
|
24055
|
+
}));
|
|
24056
|
+
return { pending, recovery };
|
|
24057
|
+
}
|
|
24058
|
+
async function markCliUserBatchPhase(store, dialogId, messageId, phase, messageIds, preparedMessages) {
|
|
24059
|
+
const key = `dialog-${dialogId}-msg-${messageId}`;
|
|
24060
|
+
const record2 = await store.read(key, { remote: false });
|
|
24061
|
+
if (!record2) throw new Error("Missing durable batch receipt");
|
|
24062
|
+
const current = record2.metadata?.cliBatchPhase;
|
|
24063
|
+
if (phase === "requested" && (current === "requested" || current === "completed")) {
|
|
24064
|
+
throw new Error(`Batch ${messageId} already requested; resubmission blocked`);
|
|
24065
|
+
}
|
|
24066
|
+
const ops = [];
|
|
24067
|
+
for (const id of messageIds) {
|
|
24068
|
+
const messageKey = `dialog-${dialogId}-msg-${id}`;
|
|
24069
|
+
const message = await store.read(messageKey, { remote: false });
|
|
24070
|
+
if (!message) throw new Error(`Missing batch user message ${id}`);
|
|
24071
|
+
const prepared = preparedMessages?.find((item) => item.cliMessageId === id);
|
|
24072
|
+
ops.push({ type: "put", key: messageKey, value: {
|
|
24073
|
+
...message,
|
|
24074
|
+
...prepared ? { content: prepared.content } : {},
|
|
24075
|
+
metadata: {
|
|
24076
|
+
...message.metadata,
|
|
24077
|
+
queueState: "accepted",
|
|
24078
|
+
...id === messageId ? { cliBatchPhase: phase, acceptedUserMessageIds: [...messageIds] } : {}
|
|
24079
|
+
}
|
|
24080
|
+
} });
|
|
24081
|
+
}
|
|
24082
|
+
await store.batch(ops);
|
|
24083
|
+
}
|
|
24084
|
+
async function rollbackCliUserBatchPhase(store, dialogId, batchId, messageIds) {
|
|
24085
|
+
const ops = [];
|
|
24086
|
+
for (const id of messageIds) {
|
|
24087
|
+
const key = `dialog-${dialogId}-msg-${id}`;
|
|
24088
|
+
const record2 = await store.read(key, { remote: false });
|
|
24089
|
+
if (!record2) continue;
|
|
24090
|
+
const metadata = { ...record2.metadata };
|
|
24091
|
+
delete metadata.cliBatchPhase;
|
|
24092
|
+
metadata.queueState = "pending";
|
|
24093
|
+
ops.push({ type: "put", key, value: { ...record2, metadata } });
|
|
24094
|
+
}
|
|
24095
|
+
if (ops.length) await store.batch(ops);
|
|
24096
|
+
}
|
|
24097
|
+
async function buildCliBatchCompletionOp(store, dialogId, batchId) {
|
|
24098
|
+
const key = `dialog-${dialogId}-msg-${batchId}`;
|
|
24099
|
+
const record2 = await store.read(key, { remote: false });
|
|
24100
|
+
if (!record2) throw new Error(`Missing batch user message ${batchId}`);
|
|
24101
|
+
return { type: "put", key, value: {
|
|
24102
|
+
...record2,
|
|
24103
|
+
metadata: { ...record2.metadata, cliBatchPhase: "completed" }
|
|
24104
|
+
} };
|
|
24105
|
+
}
|
|
24106
|
+
async function resolveCliUnknownBatchWithoutResend(store, dialogId, batchId) {
|
|
24107
|
+
const key = `dialog-${dialogId}-msg-${batchId}`;
|
|
24108
|
+
const record2 = await store.read(key, { remote: false });
|
|
24109
|
+
if (!record2 || record2.metadata?.cliBatchPhase !== "requested") throw new Error(`Unknown requested batch not found: ${batchId}`);
|
|
24110
|
+
if (record2.metadata.cliBatchResolution) return;
|
|
24111
|
+
await store.batch([{ type: "put", key, value: { ...record2, metadata: {
|
|
24112
|
+
...record2.metadata,
|
|
24113
|
+
cliBatchResolution: { decision: "continue-without-resend", decidedBy: "user", decidedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
24114
|
+
} } }]);
|
|
24115
|
+
}
|
|
22692
24116
|
|
|
22693
24117
|
// packages/agent-runtime/noloWorkspaceTools.node.ts
|
|
22694
24118
|
async function readNoloProcessStream(readable) {
|
|
@@ -22804,7 +24228,7 @@ function buildLoadSkillExecutor(args2) {
|
|
|
22804
24228
|
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
22805
24229
|
const referenceKeys = ["source", "slug", "projectBinding", "relativePath", "dbKey", "id", "skillId"];
|
|
22806
24230
|
if (referenceKeys.some((key) => Object.hasOwn(parsed, key))) {
|
|
22807
|
-
return loadPreciseSkill(args2.cwd, parsed);
|
|
24231
|
+
return loadPreciseSkill(args2.cwd, parsed, args2.agentSkillSource, args2.resolveAgentSkillSource);
|
|
22808
24232
|
}
|
|
22809
24233
|
const name = noloStringArg(parsed.name ?? parsed.skillName ?? parsed.skill);
|
|
22810
24234
|
if (!name) {
|
|
@@ -22813,12 +24237,14 @@ function buildLoadSkillExecutor(args2) {
|
|
|
22813
24237
|
metadata: { loadSkill: true, resolved: false }
|
|
22814
24238
|
};
|
|
22815
24239
|
}
|
|
22816
|
-
const { resolveSkillByName } = await import("./skillDiscovery-
|
|
24240
|
+
const { resolveSkillByName } = await import("./skillDiscovery-B5V23AXP.js");
|
|
22817
24241
|
const resolved = resolveSkillByName(args2.cwd, name);
|
|
22818
24242
|
if (!resolved) {
|
|
22819
|
-
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-
|
|
24243
|
+
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-2ECA42FC.js");
|
|
22820
24244
|
const builtin = resolveBuiltinSkillByName(name);
|
|
22821
24245
|
if (builtin) {
|
|
24246
|
+
const denied = await rejectDisabledBuiltin(args2.agentSkillSource, builtin.slug, name, args2.resolveAgentSkillSource);
|
|
24247
|
+
if (denied) return denied;
|
|
22822
24248
|
return {
|
|
22823
24249
|
content: `Skill "${name}" loaded inline. Follow its instructions.
|
|
22824
24250
|
|
|
@@ -22858,7 +24284,25 @@ ${body}`,
|
|
|
22858
24284
|
}
|
|
22859
24285
|
};
|
|
22860
24286
|
}
|
|
22861
|
-
async function
|
|
24287
|
+
async function rejectDisabledBuiltin(source, slug, requestedName, resolveSource) {
|
|
24288
|
+
if (resolveSource) {
|
|
24289
|
+
try {
|
|
24290
|
+
source = await resolveSource();
|
|
24291
|
+
} catch {
|
|
24292
|
+
source = null;
|
|
24293
|
+
}
|
|
24294
|
+
if (!source) return {
|
|
24295
|
+
content: `Skill "${requestedName}" cannot be loaded: current agent policy is unavailable.`,
|
|
24296
|
+
metadata: { loadSkill: true, resolved: false, builtin: true, policyUnavailable: true, slug, name: requestedName, requestedName }
|
|
24297
|
+
};
|
|
24298
|
+
}
|
|
24299
|
+
if (!isAgentSkillDisabled(source, slug)) return null;
|
|
24300
|
+
return {
|
|
24301
|
+
content: `Skill "${requestedName}" \u5DF2\u88AB\u7981\u7528\uFF1A\u8BE5\u80FD\u529B\u5728\u6B64 agent \u4E0A\u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5\u52A0\u8F7D\u3002`,
|
|
24302
|
+
metadata: { loadSkill: true, resolved: false, builtin: true, disabled: true, slug, name: requestedName, requestedName }
|
|
24303
|
+
};
|
|
24304
|
+
}
|
|
24305
|
+
async function loadPreciseSkill(cwd, parsed, agentSkillSource, resolveAgentSkillSource) {
|
|
22862
24306
|
const source = parsed.source;
|
|
22863
24307
|
const has2 = (key) => Object.hasOwn(parsed, key);
|
|
22864
24308
|
const reject = (reason) => ({
|
|
@@ -22875,9 +24319,11 @@ async function loadPreciseSkill(cwd, parsed) {
|
|
|
22875
24319
|
if (!nonEmpty(parsed.slug) || has2("projectBinding") || has2("relativePath")) {
|
|
22876
24320
|
return reject("builtin requires only an exact slug.");
|
|
22877
24321
|
}
|
|
22878
|
-
const { listBuiltinSkills } = await import("./builtinSkillRegistry-
|
|
24322
|
+
const { listBuiltinSkills } = await import("./builtinSkillRegistry-2ECA42FC.js");
|
|
22879
24323
|
const builtin = listBuiltinSkills().find((entry) => entry.slug === parsed.slug);
|
|
22880
24324
|
if (!builtin) return reject("builtin slug not found.");
|
|
24325
|
+
const denied = await rejectDisabledBuiltin(agentSkillSource, builtin.slug, builtin.slug, resolveAgentSkillSource);
|
|
24326
|
+
if (denied) return { ...denied, metadata: { ...denied.metadata, source } };
|
|
22881
24327
|
return {
|
|
22882
24328
|
content: `Skill "${builtin.slug}" loaded inline. Follow its instructions.
|
|
22883
24329
|
|
|
@@ -22899,7 +24345,7 @@ ${builtin.content}`,
|
|
|
22899
24345
|
}
|
|
22900
24346
|
try {
|
|
22901
24347
|
const { realpathSync, statSync, readFileSync } = await import("node:fs");
|
|
22902
|
-
const { resolve: resolve6, relative: relative6, isAbsolute: isAbsolute5, basename:
|
|
24348
|
+
const { resolve: resolve6, relative: relative6, isAbsolute: isAbsolute5, basename: basename4, sep: sep3 } = await import("node:path");
|
|
22903
24349
|
const inside = (root, target) => {
|
|
22904
24350
|
const rel = relative6(root, target);
|
|
22905
24351
|
return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep3}`) && !isAbsolute5(rel);
|
|
@@ -22908,7 +24354,7 @@ ${builtin.content}`,
|
|
|
22908
24354
|
if (!isAbsolute5(parsed.projectBinding) || realpathSync(parsed.projectBinding) !== realCwd) {
|
|
22909
24355
|
return reject("projectBinding does not match the authorized cwd.");
|
|
22910
24356
|
}
|
|
22911
|
-
if (isAbsolute5(parsed.relativePath) ||
|
|
24357
|
+
if (isAbsolute5(parsed.relativePath) || basename4(parsed.relativePath) !== "SKILL.md") {
|
|
22912
24358
|
return reject("relativePath must reference a project SKILL.md.");
|
|
22913
24359
|
}
|
|
22914
24360
|
const skillsRoot = resolve6(realCwd, ".agents", "skills");
|
|
@@ -22916,7 +24362,7 @@ ${builtin.content}`,
|
|
|
22916
24362
|
if (!inside(skillsRoot, candidate)) return reject("path is outside cwd/.agents/skills/.");
|
|
22917
24363
|
const realRoot = realpathSync(skillsRoot);
|
|
22918
24364
|
const realPath = realpathSync(candidate);
|
|
22919
|
-
if (realRoot !== skillsRoot || !inside(realRoot, realPath) ||
|
|
24365
|
+
if (realRoot !== skillsRoot || !inside(realRoot, realPath) || basename4(realPath) !== "SKILL.md") {
|
|
22920
24366
|
return reject("skill path escapes cwd/.agents/skills/ or is not SKILL.md.");
|
|
22921
24367
|
}
|
|
22922
24368
|
if (!statSync(realPath).isFile()) return reject("SKILL.md is not a file.");
|
|
@@ -22939,7 +24385,7 @@ ${body}`,
|
|
|
22939
24385
|
}
|
|
22940
24386
|
}
|
|
22941
24387
|
async function formatUnknownSkillMessage(cwd, requestedName) {
|
|
22942
|
-
const { discoverSkills } = await import("./skillDiscovery-
|
|
24388
|
+
const { discoverSkills } = await import("./skillDiscovery-B5V23AXP.js");
|
|
22943
24389
|
let available = [];
|
|
22944
24390
|
try {
|
|
22945
24391
|
available = discoverSkills(cwd).map((s) => s.name);
|
|
@@ -23604,12 +25050,16 @@ export {
|
|
|
23604
25050
|
createLocalWorkspaceToolExecutors,
|
|
23605
25051
|
buildToolParametersIndex,
|
|
23606
25052
|
getAgentRuntimeToolParametersIndex,
|
|
25053
|
+
registerLocalShellLifecycle,
|
|
25054
|
+
getLocalShellLifecycle,
|
|
23607
25055
|
normalizeLocalToolName,
|
|
23608
25056
|
isCommandExecutingTool,
|
|
23609
25057
|
resolveLocalToolPolicy,
|
|
23610
25058
|
runExecShellGates,
|
|
23611
25059
|
executeLocalToolWithPolicy,
|
|
23612
25060
|
LOCAL_TURN_ABORTED_CODE,
|
|
25061
|
+
evaluateTaskExecutionContract,
|
|
25062
|
+
projectContextProvenance,
|
|
23613
25063
|
hashToolDefinitions,
|
|
23614
25064
|
LOCAL_AGENT_CONFIG_MISSING_CODE,
|
|
23615
25065
|
runLocalAgentTurn,
|
|
@@ -23621,6 +25071,7 @@ export {
|
|
|
23621
25071
|
parseOpenAiCompatibleChatCompletionResponse,
|
|
23622
25072
|
readOpenAiCompatibleSseCompletion,
|
|
23623
25073
|
executeOpenAiCompatibleChatCompletion,
|
|
25074
|
+
describeOpenAiCompatibleRequestBudget,
|
|
23624
25075
|
resolveOpenAiCompatibleProviderConfig,
|
|
23625
25076
|
dialogMessageRecordToAgentRuntimeMessage,
|
|
23626
25077
|
buildAgentRuntimeDialogWritePlan,
|
|
@@ -23628,8 +25079,15 @@ export {
|
|
|
23628
25079
|
parseSyncServersEnv,
|
|
23629
25080
|
DEFAULT_HYBRID_READ_TIMEOUT_MS,
|
|
23630
25081
|
createHybridRecordStore,
|
|
25082
|
+
registerDialogOwner,
|
|
23631
25083
|
localDialogMessageRecordToRuntimeMessage,
|
|
23632
25084
|
buildLocalDialogWritePlan,
|
|
25085
|
+
saveCliPendingUserMessages,
|
|
25086
|
+
readCliPendingUserMessages,
|
|
25087
|
+
markCliUserBatchPhase,
|
|
25088
|
+
rollbackCliUserBatchPhase,
|
|
25089
|
+
buildCliBatchCompletionOp,
|
|
25090
|
+
resolveCliUnknownBatchWithoutResend,
|
|
23633
25091
|
buildNoloWorkspaceCliToolExecutors,
|
|
23634
25092
|
buildLoadSkillExecutor,
|
|
23635
25093
|
isStableSessionIdentityEnabled,
|