nolo-cli 0.212.0-alpha.1 → 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-KE6MBNUJ.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-N2YC5IL3.js → addContentAction-GDHDOF4U.js} +18 -17
- package/{addDialogAgentAction-3NKVQCEC.js → addDialogAgentAction-CAKRU3ZT.js} +21 -20
- package/{agentDeleteCommand-NWK7VU4N.js → agentDeleteCommand-BPV2XZL7.js} +128 -119
- package/{agentEmailCommands-UZ4DHEX2.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-HE7L2A6L.js → agentListCommands-HIZODBF3.js} +196 -124
- package/{agentMachineCommands-6TE4MBMP.js → agentMachineCommands-ZMQ2CY7Y.js} +62 -53
- 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-OI3LOENH.js → agentRunControl-JNONH3RP.js} +30 -15
- package/{agentRuntimeLocal-HL526DNQ.js → agentRuntimeLocal-QZPFWMLG.js} +52 -45
- package/{agentSlice-TMYP2UEA.js → agentSlice-RD2CDU7T.js} +20 -19
- package/{appDeleteCommands-ZERW4AXY.js → appDeleteCommands-QCCFDIEQ.js} +61 -52
- package/{appDeployCommands-DUWSMYHL.js → appDeployCommands-V2T7TNMQ.js} +61 -52
- package/{appDeployStatusCommands-N2KIE4BF.js → appDeployStatusCommands-6PGH7ZCG.js} +61 -52
- package/{appGetCommands-YVR4NPVY.js → appGetCommands-3L7WWJA6.js} +61 -52
- package/{appListCommands-JS6HOHZS.js → appListCommands-ENJCK4PO.js} +61 -52
- package/{authCommand-FE2C3ZUM.js → authCommand-6V47SYGK.js} +29 -28
- package/{authCommands-HV3EAU3V.js → authCommands-GAJ3NIXO.js} +14 -13
- package/{builtinSkillRegistry-3YOIGEF6.js → builtinSkillRegistry-2ECA42FC.js} +11 -13
- package/{chromeCommands-REEAH4SX.js → chromeCommands-G5UDKVSV.js} +3 -3
- package/{chromeOpsCommands-HEN5AX2J.js → chromeOpsCommands-YKX2QX3A.js} +20 -10
- package/{chunk-DM6UMOEL.js → chunk-27PCUMJI.js} +2 -2
- package/chunk-2CI3ZFWD.js +97 -0
- package/{chunk-HIRC32DV.js → chunk-2GJKRKI6.js} +543 -29
- package/{chunk-SM3NSZJV.js → chunk-2UCBGYO4.js} +20 -1
- package/{chunk-PYRUW7XN.js → chunk-2VUZSVAS.js} +136 -54
- package/chunk-2YGBI2XB.js +30 -0
- package/chunk-2ZKFCIJJ.js +13 -0
- package/{chunk-CJRONOYL.js → chunk-34J5K2YA.js} +19 -75
- 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-LKDF3ATR.js → chunk-5RKUPJYL.js} +1 -1
- package/{chunk-ZC3CMUKU.js → chunk-6OVNSQHN.js} +84 -2
- package/{chunk-IF45XG7K.js → chunk-6WU5572L.js} +40 -24
- package/{chunk-OHNELDTO.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-IIQ6JGRI.js → chunk-AD5EWDFD.js} +2 -2
- package/{chunk-WXYLV624.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-PJNFNEJE.js → chunk-AMEOV5VZ.js} +59 -13
- package/chunk-AN74ON4G.js +675 -0
- package/{chunk-HRMJUN5J.js → chunk-AQZ6BMRK.js} +1 -1
- package/{chunk-CQ46IRNN.js → chunk-B4GOW4MT.js} +445 -201
- 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-D2MDMY2M.js → chunk-BV3FLP2L.js} +47 -1
- package/{chunk-25JZEIXN.js → chunk-C4VAR65S.js} +92 -150
- package/{chunk-AVTVGMDY.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-M6RL5JCD.js → chunk-CMZ3Z5PT.js} +14 -14
- package/{secretCommands-4QS3HCA2.js → chunk-D726I5AZ.js} +191 -16
- package/{chunk-INSBKSBB.js → chunk-DNKTQ3IN.js} +4 -4
- package/chunk-DVQH4BTR.js +1137 -0
- package/{chunk-SOHTHFV2.js → chunk-DWX2HEVC.js} +91 -132
- package/{chunk-NOMIGOST.js → chunk-EIAI3PPH.js} +116 -124
- package/chunk-EUCFKKDM.js +247 -0
- package/chunk-EWQ3HGNZ.js +90 -0
- package/{chunk-RPQXPZZF.js → chunk-F3GRJO4Z.js} +908 -13
- package/{chunk-GSQNH63I.js → chunk-FIYSMXHY.js} +3 -19
- package/{chunk-KSTEXKL6.js → chunk-FJ23FZXF.js} +76 -31
- package/{chunk-INN4LTAJ.js → chunk-FJK526XH.js} +2 -2
- package/chunk-FS2XP5D7.js +142 -0
- package/{chunk-QT6PKHYJ.js → chunk-FYF2TONJ.js} +5 -5
- package/{chunk-OXME3PEE.js → chunk-GBWGPTA7.js} +2 -1
- package/{chunk-RU4SD66C.js → chunk-GYVCJABP.js} +30 -254
- package/{chunk-YUXQAVRD.js → chunk-HOCHUZQ7.js} +257 -90
- package/{chunk-Y2WUYX4I.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-5RYBGBQH.js → chunk-IILMY4W4.js} +14 -9
- package/chunk-JA3ICVJY.js +271 -0
- package/{chunk-ZRSNONOB.js → chunk-JWXITTQB.js} +8 -3
- package/{chunk-JNKSDZFS.js → chunk-KEN3N2TN.js} +310 -66
- 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-6OQUPIQF.js → chunk-LVL6GFCM.js} +4 -4
- package/{chunk-UTV2AYEG.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-B7NJ3T4A.js → chunk-MS4NZNKI.js} +10 -10
- package/{chunk-3AKFVZ2I.js → chunk-MYHNBEXD.js} +3 -3
- package/{chunk-VZKUKCA6.js → chunk-MZLE5HQ3.js} +3673 -241
- package/{chunk-AZMYUSVF.js → chunk-N5Z2V73W.js} +1 -1
- package/chunk-NIZ2BXFD.js +526 -0
- package/{chunk-YPD3VJZW.js → chunk-NWP2OYOX.js} +20 -20
- package/{chunk-3FOQHGHN.js → chunk-O6J3OTOP.js} +4 -4
- package/{chunk-3RQVYR4B.js → chunk-OB6DVWPF.js} +197 -65
- package/{chunk-YWSEPJ7C.js → chunk-OBWT45ZU.js} +3 -3
- package/{chunk-5AQR3DGV.js → chunk-ODJ7BVSI.js} +80 -11
- package/{chunk-XJWWBO34.js → chunk-OJKUU3LP.js} +5 -7
- package/{chunk-GNDJKC4B.js → chunk-ON37YXGX.js} +29 -29
- package/{chunk-D5RCRX4A.js → chunk-P5ZJRTCH.js} +9415 -5169
- package/{chunk-6XIE5ZGI.js → chunk-PDCV7P5W.js} +1 -1
- package/{chunk-EZFQ6XRV.js → chunk-PJCIP64Z.js} +861 -59
- package/{chunk-GPO7FCEZ.js → chunk-PJVKMGPZ.js} +1222 -1719
- package/{chunk-CKAHAVMK.js → chunk-PPJYZRSQ.js} +40 -26
- package/chunk-QHEN7NZ7.js +46 -0
- package/{chunk-4KH4J3G5.js → chunk-QNWG52I4.js} +19 -7
- package/{chunk-YGILMZ7N.js → chunk-QVBXJNZ2.js} +1 -1
- package/chunk-RDH5CQ4T.js +1382 -0
- 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-IAPCBNEE.js → chunk-SQYIK6HO.js} +1 -1
- package/{chunk-22CIEBYO.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-6NSSLV67.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-MMNYUVLW.js → chunk-UB3D4TRQ.js} +11 -77
- package/{chunk-WPORQFYN.js → chunk-UVLYNWIE.js} +2 -2
- package/{chunk-YOIW77S2.js → chunk-UYOICCYG.js} +29 -19
- package/{chunk-4I7ERB7F.js → chunk-VREDDN25.js} +1 -1
- package/{chunk-JIT6FSXJ.js → chunk-WAE3GFCJ.js} +3 -3
- package/{chunk-IJXYFTV7.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-YJMRHHGY.js → chunk-WUUH4LWZ.js} +60 -30
- package/{chunk-PDGKOTO7.js → chunk-X7UF53VA.js} +33 -22
- package/{chunk-TY3TIUJK.js → chunk-XI2BWJM5.js} +65 -0
- package/{chunk-OOF4UPC5.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-NJR3WKVP.js → chunk-YWWDC3O7.js} +281 -159
- package/chunk-YZMNK53S.js +68 -0
- package/{chunk-FHU44LN3.js → chunk-Z2PITYZN.js} +2179 -552
- 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-VVMTPFAX.js → commandRegistry-5DA5UP7S.js} +106 -98
- package/{contentThunks-N52O67MI.js → contentThunks-5GUQ7FWJ.js} +47 -43
- package/{cooldownCommands-YXLWOXWR.js → cooldownCommands-X7P5M2V5.js} +5 -4
- package/{createAgentAutomationAction-ZC57YRSV.js → createAgentAutomationAction-UCLTHQRI.js} +51 -49
- package/{createDialogAction-VQW5WDYX.js → createDialogAction-UPN774AF.js} +46 -48
- package/{createPageAction-M5VDA7SC.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-HP7G4LX3.js → dbSlice-WNON7TOL.js} +17 -16
- package/{deleteFile-7VQGLK2V.js → deleteFile-Q3YDB4ML.js} +9 -9
- package/{desktopFolderProjects-SFY5EZS3.js → desktopFolderProjects-4POAMVJN.js} +2 -2
- package/{dialogCommands-JHMR2N2Y.js → dialogCommands-VRI7VCXH.js} +64 -57
- package/dialogNotifyCommand-6TMCX4D2.js +36 -0
- package/{dialogSlice-GRSVGDTF.js → dialogSlice-LFNVUSAN.js} +42 -40
- package/{dialogUsageCommand-7KCPYGHG.js → dialogUsageCommand-HTVPR2CX.js} +11 -10
- package/{docCreateCommands-F2K3UPSQ.js → docCreateCommands-AMPXMOX3.js} +61 -54
- package/{docDeleteCommands-XGXB5RFT.js → docDeleteCommands-I5WFAEHP.js} +63 -57
- package/{docReadCommands-7HWZZV6J.js → docReadCommands-X53ELNIE.js} +61 -54
- package/{docStore-KNZK6Y2G.js → docStore-2VAWVLWH.js} +21 -20
- package/{docUpdateCommands-OZZ7NQII.js → docUpdateCommands-6QPNDC7M.js} +64 -57
- package/{fetchMessages-M3QU7ZCQ.js → fetchMessages-TQEUZD7H.js} +8 -7
- package/{getPricing-2MNMXEVG.js → getPricing-MB2GBXOK.js} +6 -6
- package/{handleSendMessageAction-SHIH74GJ.js → handleSendMessageAction-AAJOHXOB.js} +193 -301
- package/{hostCredentialCreate-X64WK4JD.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-XRLAH4CZ.js → localDialogRead-SVTPA5GY.js} +3 -3
- package/{localFirstLog-DHNOY2NA.js → localFirstLog-OIETGK66.js} +1 -1
- package/localRecall-2J6QPOK2.js +15 -0
- package/{localRuntimeAdapter-A7K3ABA6.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-DE3MR7CJ.js → machineCommands-3MLIAK5Q.js} +128 -119
- package/{machineInfo-UKPTZO5Y.js → machineInfo-LWHTEBHJ.js} +1 -1
- package/machineWsRunDispatch-FKIGROQF.js +191 -0
- package/{memberThunks-7WJAY5V6.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-GGL5HLMD.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-4VZQODSN.js → read-MRQHJMJ2.js} +10 -10
- package/{readDocTool-AVD32RUJ.js → readDocTool-4BGTXTXA.js} +2 -2
- package/{readlineWorkspace-XKYKNL2I.js → readlineWorkspace-AKAHSCNY.js} +6505 -4634
- package/{removeDialogAgentAction-FKL4BYMR.js → removeDialogAgentAction-B6H7DXFM.js} +23 -22
- package/{runAgentClientLoop-V7E2WBVM.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-TLIOLWWI.js → setDialogExtraReferencesAction-EVCY3TRW.js} +22 -21
- package/{setPrimaryDialogAgentAction-2OLWRFYR.js → setPrimaryDialogAgentAction-KPFVPHCJ.js} +23 -22
- package/{settingThunks-UGBPCNYF.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-4KSLKVNF.js → spaceCommands-DTTNAS2L.js} +61 -53
- package/store-JRVN62NM.js +46 -0
- package/{streamAgentChatTurn-7FR7X2NU.js → streamAgentChatTurn-R5UY25VB.js} +875 -618
- package/{switchDialogAgentAction-UZSAG2N5.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-ZLKCC25W.js → tools-HWFG6GMJ.js} +75 -74
- package/tuiSummaryLlmCaller-HQQZAMYF.js +44 -0
- package/{updateCommands-4744PL3P.js → updateCommands-RJVCRSBP.js} +10 -8
- package/{updateDialogTitleAction-U53ZT7PJ.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-XSQVF2GK.js → windowsSelfUpdate-KERHIAB4.js} +3 -3
- package/{workloadLifecycle-4BEQHMSD.js → workloadLifecycle-DYNEYHV5.js} +7 -6
- package/agentRecordCommands-L3QQ7HZ4.js +0 -167
- package/agentRunCommand-2IFGQHCO.js +0 -196
- package/chunk-3CGG2PAL.js +0 -594
- package/chunk-5XBUWM6I.js +0 -89
- package/chunk-BFM34N54.js +0 -842
- package/chunk-CJEIOP3E.js +0 -0
- package/chunk-CZM5YTZ7.js +0 -977
- package/chunk-EYUBHHFB.js +0 -636
- package/chunk-JTDORD5P.js +0 -415
- package/chunk-NRFKLKRU.js +0 -339
- package/chunk-VPAZOH2D.js +0 -115
- package/chunk-WJZOQR2J.js +0 -151
- package/chunk-ZCWRMUWT.js +0 -89
- package/dist-M676ULYG.js +0 -7314
- package/machineWsRunDispatch-R26P5V36.js +0 -182
- package/models-PJBE6JDV.js +0 -9
- package/tuiSummaryLlmCaller-WC54MVGP.js +0 -160
- 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-4KH4J3G5.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,36 +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-25JZEIXN.js";
|
|
126
|
-
import {
|
|
127
|
-
applyToolSurfaceConstraints
|
|
128
|
-
} from "./chunk-KC4XDTT3.js";
|
|
129
|
-
import {
|
|
130
|
-
clipToolText,
|
|
131
|
-
resolveHistoricalToolContentCap,
|
|
132
|
-
resolveToolOutputProfile
|
|
133
|
-
} from "./chunk-2WZXXAQD.js";
|
|
139
|
+
isQuotaExhaustedError
|
|
140
|
+
} from "./chunk-TLE77UJ5.js";
|
|
134
141
|
import {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
} from "./chunk-YWSEPJ7C.js";
|
|
142
|
+
isAgentSkillDisabled
|
|
143
|
+
} from "./chunk-FS2XP5D7.js";
|
|
138
144
|
import {
|
|
139
145
|
buildDialogFallbackTitleFromUserInput
|
|
140
146
|
} from "./chunk-2MBTWINN.js";
|
|
@@ -142,32 +148,34 @@ import {
|
|
|
142
148
|
EMPTY_ASSISTANT_REPAIR_PROMPT,
|
|
143
149
|
extractReferenceKeysFromMessage,
|
|
144
150
|
hasAssistantVisibleOutput,
|
|
145
|
-
normalizeUsage,
|
|
146
|
-
readCacheCreationInputTokens,
|
|
147
|
-
readCacheReadInputTokens,
|
|
148
151
|
resolveAgentContextWindow,
|
|
149
152
|
resolveEmptyAssistantFallbackMessage,
|
|
150
153
|
resolveEmptyAssistantOutcome,
|
|
151
154
|
resolveTruncatedReasoningTailLog
|
|
152
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-NIZ2BXFD.js";
|
|
153
156
|
import {
|
|
154
157
|
COMPACTION_SUMMARY_SCHEMA_VERSION,
|
|
155
158
|
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|
|
156
|
-
|
|
159
|
+
buildBoundedCompactionRequest,
|
|
157
160
|
buildCompactionMetricsFromPlan,
|
|
158
|
-
|
|
159
|
-
computeSummaryInputTokenCap,
|
|
161
|
+
classifySummaryError,
|
|
160
162
|
computeSummarySourceMetadata,
|
|
163
|
+
createSummaryBudget,
|
|
161
164
|
formatCompactionMetricsLog,
|
|
162
|
-
|
|
163
|
-
formatMessagesForSummaryWithTruncation,
|
|
165
|
+
getMessageTokenCount,
|
|
164
166
|
getModelContextWindow,
|
|
167
|
+
isTruncatedCompletion,
|
|
168
|
+
normalizeUsage,
|
|
165
169
|
planCompression,
|
|
166
|
-
|
|
170
|
+
readCacheCreationInputTokens,
|
|
171
|
+
readCacheReadInputTokens,
|
|
167
172
|
resolveCompressionTriggerRatio,
|
|
173
|
+
resolveEffectiveCompactionBudgets,
|
|
174
|
+
runSummaryWithContract,
|
|
168
175
|
sha256Hex,
|
|
176
|
+
summaryCompletionTokens,
|
|
169
177
|
truncateToolOutputForContext
|
|
170
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-RDH5CQ4T.js";
|
|
171
179
|
import {
|
|
172
180
|
createProviderCallTimingTracker,
|
|
173
181
|
finalizeProviderCallTiming,
|
|
@@ -178,25 +186,38 @@ import {
|
|
|
178
186
|
import {
|
|
179
187
|
clipCompactText
|
|
180
188
|
} from "./chunk-5MMAK75Q.js";
|
|
181
|
-
import {
|
|
182
|
-
assertCredentialRef
|
|
183
|
-
} from "./chunk-OQHIVPG4.js";
|
|
184
189
|
import {
|
|
185
190
|
asRecordOrEmpty
|
|
186
191
|
} from "./chunk-KX6YBIHG.js";
|
|
192
|
+
import {
|
|
193
|
+
assertCredentialRef
|
|
194
|
+
} from "./chunk-SNBZZPYH.js";
|
|
195
|
+
import {
|
|
196
|
+
isLevelNotFoundError
|
|
197
|
+
} from "./chunk-OW765XBU.js";
|
|
187
198
|
import {
|
|
188
199
|
isAbortError
|
|
189
200
|
} from "./chunk-7DPNBQSV.js";
|
|
190
201
|
import {
|
|
191
|
-
|
|
192
|
-
} from "./chunk-
|
|
193
|
-
import {
|
|
194
|
-
buildUserResponseLanguageContext
|
|
195
|
-
} from "./chunk-4VJAC32I.js";
|
|
202
|
+
WORKTREE_ISOLATION_PRELUDE
|
|
203
|
+
} from "./chunk-PJCIP64Z.js";
|
|
196
204
|
import {
|
|
197
205
|
canonicalizeToolName,
|
|
198
206
|
canonicalizeToolNames
|
|
199
|
-
} 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";
|
|
200
221
|
import {
|
|
201
222
|
buildInteractiveCommandBlockedResult,
|
|
202
223
|
buildProcessTaskResultCapsule,
|
|
@@ -211,56 +232,54 @@ import {
|
|
|
211
232
|
formatToolOverflowMarker,
|
|
212
233
|
getProcessRegistry,
|
|
213
234
|
isProcessTaskTerminalStatus,
|
|
235
|
+
isSpilledToolOutput,
|
|
214
236
|
reportedTaskStatus,
|
|
215
237
|
resolveExecShellTimeoutMs,
|
|
216
238
|
resolveExecutableOnPath,
|
|
217
239
|
runWorkspaceCommand,
|
|
218
240
|
spawnToWebStreams,
|
|
241
|
+
spillLargeToolOutput,
|
|
219
242
|
spillToolOutput,
|
|
220
243
|
toProcessTaskView,
|
|
221
244
|
truncateToolOutput
|
|
222
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-KEN3N2TN.js";
|
|
223
246
|
import {
|
|
224
247
|
estimateTokenCount
|
|
225
248
|
} from "./chunk-PSCNXBYA.js";
|
|
226
249
|
import {
|
|
227
250
|
buildProviderAuthHeaders,
|
|
228
251
|
buildProviderExecutionPlan
|
|
229
|
-
} from "./chunk-
|
|
252
|
+
} from "./chunk-I7WBYGBP.js";
|
|
230
253
|
import {
|
|
231
254
|
toErrorMessage
|
|
232
255
|
} from "./chunk-HNMXYYJR.js";
|
|
256
|
+
import {
|
|
257
|
+
asTrimmedString
|
|
258
|
+
} from "./chunk-3EUW3WEO.js";
|
|
233
259
|
import {
|
|
234
260
|
isRecord
|
|
235
261
|
} from "./chunk-KUG52IAP.js";
|
|
262
|
+
import {
|
|
263
|
+
PLATFORM_HOSTED_DEEPSEEK_FLASH_MODEL
|
|
264
|
+
} from "./chunk-CKG3PRZ7.js";
|
|
236
265
|
import {
|
|
237
266
|
asTrimmedLowercaseString
|
|
238
267
|
} from "./chunk-QSJ3HFEF.js";
|
|
239
|
-
import {
|
|
240
|
-
normalizeServerOrigin
|
|
241
|
-
} from "./chunk-CF7PE763.js";
|
|
242
|
-
import {
|
|
243
|
-
resolveNoloStateDir
|
|
244
|
-
} from "./chunk-6UBGXX2W.js";
|
|
245
|
-
import {
|
|
246
|
-
dialogMessageKey,
|
|
247
|
-
dialogMessageRange
|
|
248
|
-
} from "./chunk-XJWWBO34.js";
|
|
249
|
-
import {
|
|
250
|
-
asTrimmedNonEmptyStringArray
|
|
251
|
-
} from "./chunk-I42VC5KR.js";
|
|
252
268
|
import {
|
|
253
269
|
asOptionalPositiveFiniteNumber
|
|
254
270
|
} from "./chunk-U6VC4MU4.js";
|
|
255
|
-
import {
|
|
256
|
-
asTrimmedString
|
|
257
|
-
} from "./chunk-3EUW3WEO.js";
|
|
258
271
|
import {
|
|
259
272
|
asOptionalTrimmedString
|
|
260
273
|
} from "./chunk-G3SUCT4W.js";
|
|
274
|
+
import {
|
|
275
|
+
normalizeServerOrigin
|
|
276
|
+
} from "./chunk-CF7PE763.js";
|
|
277
|
+
import {
|
|
278
|
+
resolveNoloStateDir
|
|
279
|
+
} from "./chunk-6UBGXX2W.js";
|
|
261
280
|
import {
|
|
262
281
|
__export
|
|
263
|
-
} from "./chunk-
|
|
282
|
+
} from "./chunk-U67V476Y.js";
|
|
264
283
|
|
|
265
284
|
// packages/agent-runtime/actionGate.ts
|
|
266
285
|
function readCommandActionGatePayload(payload) {
|
|
@@ -304,6 +323,42 @@ function readTitleParams(value) {
|
|
|
304
323
|
return Object.fromEntries(entries);
|
|
305
324
|
}
|
|
306
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
|
+
|
|
307
362
|
// node_modules/effect/dist/Pipeable.js
|
|
308
363
|
var pipeArguments = (self, args2) => {
|
|
309
364
|
switch (args2.length) {
|
|
@@ -13127,6 +13182,30 @@ function createLoopTiming() {
|
|
|
13127
13182
|
return { mark, flush: flush2 };
|
|
13128
13183
|
}
|
|
13129
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
|
+
|
|
13130
13209
|
// packages/agent-runtime/toolCallPairing.ts
|
|
13131
13210
|
function readToolCallId(message) {
|
|
13132
13211
|
if (typeof message.tool_call_id === "string" && message.tool_call_id) {
|
|
@@ -13485,7 +13564,7 @@ var OBSERVATION_ONLY_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
|
13485
13564
|
]);
|
|
13486
13565
|
function formatToolMessageContent(args2) {
|
|
13487
13566
|
const sanitizedContent = sanitizeToolOutputText(args2.content ?? "");
|
|
13488
|
-
const scrubbedContent = scrubSecrets(sanitizedContent).cleaned;
|
|
13567
|
+
const scrubbedContent = spillLargeToolOutput(scrubSecrets(sanitizedContent).cleaned, args2.toolName, args2.workspaceRoot);
|
|
13489
13568
|
if (args2.toolName !== "globFiles" && args2.toolName !== "codeSearch" && args2.toolName !== "readFile" || !args2.metadata || Object.keys(args2.metadata).length === 0) {
|
|
13490
13569
|
return scrubbedContent;
|
|
13491
13570
|
}
|
|
@@ -13501,7 +13580,7 @@ function formatToolMessageContent(args2) {
|
|
|
13501
13580
|
[tool metadata]
|
|
13502
13581
|
${JSON.stringify(visible)}`;
|
|
13503
13582
|
}
|
|
13504
|
-
function blocksToOpenAiMessages(blocks) {
|
|
13583
|
+
function blocksToOpenAiMessages(blocks, workspaceRoot) {
|
|
13505
13584
|
const out = [];
|
|
13506
13585
|
let text2 = "";
|
|
13507
13586
|
let reasoning = "";
|
|
@@ -13522,6 +13601,7 @@ function blocksToOpenAiMessages(blocks) {
|
|
|
13522
13601
|
role: "tool",
|
|
13523
13602
|
content: formatToolMessageContent({
|
|
13524
13603
|
toolName: tc.function.name,
|
|
13604
|
+
workspaceRoot,
|
|
13525
13605
|
content: res?.content ?? "",
|
|
13526
13606
|
...res?.metadata ? { metadata: res.metadata } : {}
|
|
13527
13607
|
}),
|
|
@@ -13588,42 +13668,6 @@ var TOOL_METADATA_KEYS = [
|
|
|
13588
13668
|
"pasteId",
|
|
13589
13669
|
"source"
|
|
13590
13670
|
];
|
|
13591
|
-
function trimHistoryToContextBudget(history, model, contextWindowOverride) {
|
|
13592
|
-
if (history.length === 0) return { history, droppedCount: 0 };
|
|
13593
|
-
const { rawMessageBudget } = planContextUsage({
|
|
13594
|
-
contextWindow: contextWindowOverride ?? getModelContextWindow(model ?? ""),
|
|
13595
|
-
summaryTokens: 0,
|
|
13596
|
-
// localLoop 没有 web 端的负载分档器;medium 是中性默认值,
|
|
13597
|
-
// 不为了省几个 token 在这里复制一份分类逻辑。
|
|
13598
|
-
recentLoad: "medium"
|
|
13599
|
-
});
|
|
13600
|
-
const messageTokens = (message) => {
|
|
13601
|
-
const toolCalls = message.tool_calls;
|
|
13602
|
-
return estimateTokenCount(contentAsText(message.content)) + (Array.isArray(toolCalls) ? estimateTokenCount(JSON.stringify(toolCalls)) : 0);
|
|
13603
|
-
};
|
|
13604
|
-
let used = 0;
|
|
13605
|
-
let start = history.length;
|
|
13606
|
-
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
13607
|
-
const cost = messageTokens(history[i]);
|
|
13608
|
-
if (used + cost > rawMessageBudget && start < history.length) break;
|
|
13609
|
-
used += cost;
|
|
13610
|
-
start = i;
|
|
13611
|
-
}
|
|
13612
|
-
if (start === 0) return { history, droppedCount: 0 };
|
|
13613
|
-
return {
|
|
13614
|
-
history: sanitizeToolCallPairing(history.slice(start)),
|
|
13615
|
-
droppedCount: start
|
|
13616
|
-
};
|
|
13617
|
-
}
|
|
13618
|
-
function contentAsText(content) {
|
|
13619
|
-
if (typeof content === "string") return content;
|
|
13620
|
-
if (!Array.isArray(content)) return "";
|
|
13621
|
-
return content.map((part) => {
|
|
13622
|
-
if (part?.type === "text") return part.text;
|
|
13623
|
-
if (part?.type === "image_url") return part.image_url.url;
|
|
13624
|
-
return "";
|
|
13625
|
-
}).join("\n");
|
|
13626
|
-
}
|
|
13627
13671
|
function contentCharCount(content) {
|
|
13628
13672
|
if (typeof content === "string") return content.length;
|
|
13629
13673
|
if (!Array.isArray(content)) return 0;
|
|
@@ -13657,6 +13701,7 @@ function projectToolContentForProvider(args2) {
|
|
|
13657
13701
|
const rawContent = args2.content;
|
|
13658
13702
|
const content = typeof rawContent === "string" ? sanitizeToolOutputText(rawContent) : rawContent;
|
|
13659
13703
|
if (typeof content !== "string") return content;
|
|
13704
|
+
if (isSpilledToolOutput(content)) return content;
|
|
13660
13705
|
const metadataText = compactToolMetadata(args2.metadata);
|
|
13661
13706
|
const embeddedMetadataIndex = metadataText ? content.indexOf("\n\n[tool metadata]\n") : -1;
|
|
13662
13707
|
const contentForProjection = embeddedMetadataIndex >= 0 ? content.slice(0, embeddedMetadataIndex) : content;
|
|
@@ -13688,7 +13733,7 @@ ${metadataText}` : "";
|
|
|
13688
13733
|
content: contentForProjection,
|
|
13689
13734
|
toolName: args2.toolName
|
|
13690
13735
|
});
|
|
13691
|
-
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`;
|
|
13692
13737
|
} catch {
|
|
13693
13738
|
}
|
|
13694
13739
|
}
|
|
@@ -13898,6 +13943,29 @@ ${args2.input}` : [
|
|
|
13898
13943
|
} : {}
|
|
13899
13944
|
};
|
|
13900
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
|
+
}
|
|
13901
13969
|
|
|
13902
13970
|
// packages/agent-runtime/toolArgsTruncationPolicy.ts
|
|
13903
13971
|
import { createHash } from "node:crypto";
|
|
@@ -14738,12 +14806,13 @@ function detectExecShellSynchronousWarnings(command, shell) {
|
|
|
14738
14806
|
}
|
|
14739
14807
|
|
|
14740
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.` : "";
|
|
14741
14810
|
function buildExecShellToolDefinition(toolName = "execShell") {
|
|
14742
14811
|
return {
|
|
14743
14812
|
type: "function",
|
|
14744
14813
|
function: {
|
|
14745
14814
|
name: toolName,
|
|
14746
|
-
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.`,
|
|
14747
14816
|
parameters: {
|
|
14748
14817
|
type: "object",
|
|
14749
14818
|
properties: {
|
|
@@ -14761,7 +14830,7 @@ function buildExecShellToolDefinition(toolName = "execShell") {
|
|
|
14761
14830
|
},
|
|
14762
14831
|
label: {
|
|
14763
14832
|
type: "string",
|
|
14764
|
-
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."
|
|
14765
14834
|
}
|
|
14766
14835
|
}
|
|
14767
14836
|
}
|
|
@@ -15037,14 +15106,14 @@ var configuredConcurrency = Number(process.env.NOLO_VISUAL_RENDERER_CONCURRENCY
|
|
|
15037
15106
|
var renderSlots = new VisualRenderSemaphore(Number.isFinite(configuredConcurrency) ? Math.max(1, Math.min(2, Math.floor(configuredConcurrency))) : 2);
|
|
15038
15107
|
var require2 = createRequire(import.meta.url);
|
|
15039
15108
|
function visualRendererCapability() {
|
|
15040
|
-
if (process.env.NOLO_VISUAL_RENDERER_DISABLED === "1") return { available: false, reason: "Platform renderer disabled by NOLO_VISUAL_RENDERER_DISABLED=1 on this runtime host." };
|
|
15109
|
+
if (process.env.NOLO_VISUAL_RENDERER_DISABLED === "1") return { available: false, reasonCode: "disabled", reason: "Platform renderer disabled by NOLO_VISUAL_RENDERER_DISABLED=1 on this runtime host." };
|
|
15041
15110
|
try {
|
|
15042
15111
|
const { chromium } = require2("playwright");
|
|
15043
15112
|
const executablePath = [chromium.executablePath(), resolveExecutableOnPath("google-chrome"), resolveExecutableOnPath("chromium"), resolveExecutableOnPath("chromium-browser")].find((path) => !!path && existsSync(path));
|
|
15044
|
-
if (!executablePath) return { available: false, reason: "No Chromium renderer installed. Install Playwright Chromium (playwright install chromium) or system Chromium/Google Chrome on the runtime host." };
|
|
15113
|
+
if (!executablePath) return { available: false, reasonCode: "missing-browser", reason: "No Chromium renderer installed. Install Playwright Chromium (playwright install chromium) or system Chromium/Google Chrome on the runtime host." };
|
|
15045
15114
|
return { available: true, chromium, executablePath };
|
|
15046
15115
|
} catch {
|
|
15047
|
-
return { available: false, reason: "Platform renderer unavailable: install the platform Playwright dependency and Chromium on the runtime host (not a workspace npm script)." };
|
|
15116
|
+
return { available: false, reasonCode: "dependency-unavailable", reason: "Platform renderer unavailable: install the platform Playwright dependency and Chromium on the runtime host (not a workspace npm script)." };
|
|
15048
15117
|
}
|
|
15049
15118
|
}
|
|
15050
15119
|
async function renderVisualPage(args2) {
|
|
@@ -15319,6 +15388,52 @@ import { homedir } from "node:os";
|
|
|
15319
15388
|
import { dirname as dirname2, relative as relative4, resolve as resolve4, sep as sep2 } from "node:path";
|
|
15320
15389
|
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
15321
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
|
+
|
|
15322
15437
|
// packages/core/readRangeLedger.ts
|
|
15323
15438
|
function filterRetainedLedgerRecords(records, retainedCap) {
|
|
15324
15439
|
return records.filter((record2) => record2.chars <= retainedCap);
|
|
@@ -15353,15 +15468,27 @@ function isLineRangeCovered(request3, covered) {
|
|
|
15353
15468
|
|
|
15354
15469
|
// packages/agent-runtime/fileTextSearch.ts
|
|
15355
15470
|
import { readdir, readFile as readFile3, stat as stat3 } from "node:fs/promises";
|
|
15356
|
-
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";
|
|
15357
15472
|
import { spawn as spawnChildProcess } from "node:child_process";
|
|
15358
15473
|
|
|
15359
15474
|
// packages/agent-runtime/gitignore.ts
|
|
15360
15475
|
import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
15361
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
|
+
}
|
|
15362
15484
|
async function readRootGitignorePatterns(workspaceRoot) {
|
|
15363
|
-
|
|
15364
|
-
|
|
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
|
+
}
|
|
15365
15492
|
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && !line.startsWith("!")).flatMap((line) => {
|
|
15366
15493
|
const unanchored = line.replace(/^\//, "");
|
|
15367
15494
|
if (unanchored.endsWith("/")) return [`${unanchored}**`];
|
|
@@ -15373,14 +15500,15 @@ async function hasRootGitignore(workspaceRoot) {
|
|
|
15373
15500
|
try {
|
|
15374
15501
|
await stat2(resolve(workspaceRoot, ".gitignore"));
|
|
15375
15502
|
return true;
|
|
15376
|
-
} catch {
|
|
15377
|
-
return false;
|
|
15503
|
+
} catch (err) {
|
|
15504
|
+
if (isIgnorableFsError(err)) return false;
|
|
15505
|
+
throw err;
|
|
15378
15506
|
}
|
|
15379
15507
|
}
|
|
15380
15508
|
|
|
15381
15509
|
// packages/agent-runtime/fileTextSearch.ts
|
|
15382
15510
|
var normalizePath = (value) => value.replaceAll("\\", "/");
|
|
15383
|
-
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));
|
|
15384
15512
|
var COMMAND_LIMIT_HEADROOM = 1;
|
|
15385
15513
|
async function runCommand(binary, args2, cwd, maxResults) {
|
|
15386
15514
|
const recordLimit = maxResults === void 0 ? 0 : Math.max(0, maxResults) + COMMAND_LIMIT_HEADROOM;
|
|
@@ -15406,6 +15534,17 @@ async function runCommand(binary, args2, cwd, maxResults) {
|
|
|
15406
15534
|
}
|
|
15407
15535
|
});
|
|
15408
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
|
+
}
|
|
15409
15548
|
function commandArgs(o, binary, target) {
|
|
15410
15549
|
const args2 = binary === "rg" ? ["--line-number", "--no-heading", "--color", "never", "--null"] : ["-RIn", "--binary-files=without-match", "--null"];
|
|
15411
15550
|
if (binary === "rg") args2.push("--no-require-git");
|
|
@@ -15418,8 +15557,8 @@ function commandArgs(o, binary, target) {
|
|
|
15418
15557
|
if (o.include) args2.push("--glob", o.include);
|
|
15419
15558
|
} else {
|
|
15420
15559
|
for (const x of o.exclude ?? []) {
|
|
15421
|
-
const clean = x
|
|
15422
|
-
if (clean
|
|
15560
|
+
const clean = extractGrepExcludeDir(x);
|
|
15561
|
+
if (clean) args2.push("--exclude-dir", clean);
|
|
15423
15562
|
}
|
|
15424
15563
|
if (o.include) args2.push("--include", o.include);
|
|
15425
15564
|
}
|
|
@@ -15467,7 +15606,7 @@ function globMatch(pattern, value) {
|
|
|
15467
15606
|
else source += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
15468
15607
|
}
|
|
15469
15608
|
const r = new RegExp(`^${source}$`);
|
|
15470
|
-
return r.test(value) || r.test(
|
|
15609
|
+
return r.test(value) || r.test(basename2(value));
|
|
15471
15610
|
}
|
|
15472
15611
|
var defaultReadTextFile = (filePath) => readFile3(filePath, "utf8").catch(() => "");
|
|
15473
15612
|
async function jsSearch(o, targetPath) {
|
|
@@ -15515,6 +15654,23 @@ async function jsSearch(o, targetPath) {
|
|
|
15515
15654
|
}
|
|
15516
15655
|
return { matches: out, totalMatches: out.length, truncated: false, engine: "js" };
|
|
15517
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
|
+
}
|
|
15518
15674
|
var COMMAND_ENGINES = [
|
|
15519
15675
|
{ engine: "ripgrep", binaryOption: "resolveRipgrepBinary", binaryName: "rg", argsKey: "rg" },
|
|
15520
15676
|
{ engine: "grep", binaryOption: "resolveGrepBinary", binaryName: "grep", argsKey: "grep" }
|
|
@@ -15526,6 +15682,7 @@ async function searchFileTextMatches(o) {
|
|
|
15526
15682
|
if (targetStat.isFile()) return jsSearch(o, targetPath);
|
|
15527
15683
|
const run2 = o.runCommand ?? runCommand, max4 = o.maxResults;
|
|
15528
15684
|
for (const entry of COMMAND_ENGINES) {
|
|
15685
|
+
if (entry.engine === "grep" && !await canGrepFulfillOptions(o)) continue;
|
|
15529
15686
|
const injectedResolver = o[entry.binaryOption];
|
|
15530
15687
|
const binary = injectedResolver ? injectedResolver() : resolveExecutableOnPath(entry.binaryName);
|
|
15531
15688
|
if (!binary) continue;
|
|
@@ -15557,8 +15714,11 @@ function readProcessOwner(runtimeContext) {
|
|
|
15557
15714
|
if (!dialogId) return null;
|
|
15558
15715
|
const turnId = asNonEmptyString(runtimeContext.turnId);
|
|
15559
15716
|
const ownerId = asNonEmptyString(runtimeContext.ownerId);
|
|
15717
|
+
const getDepth = runtimeContext.getProcessCausalDepth;
|
|
15718
|
+
const depth = typeof getDepth === "function" ? getDepth() : runtimeContext.processCausalDepth;
|
|
15560
15719
|
return {
|
|
15561
15720
|
dialogId,
|
|
15721
|
+
...typeof depth === "number" && Number.isSafeInteger(depth) && depth >= 0 ? { processCausalDepth: depth } : {},
|
|
15562
15722
|
...turnId ? { turnId } : {},
|
|
15563
15723
|
...ownerId ? { ownerId } : {}
|
|
15564
15724
|
};
|
|
@@ -15707,13 +15867,15 @@ function runTaskLogs(args2) {
|
|
|
15707
15867
|
const allEvents = registry.getTaskEvents(taskId, 0);
|
|
15708
15868
|
const terminal = lastTerminalEvent(allEvents);
|
|
15709
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;
|
|
15710
15871
|
return {
|
|
15711
15872
|
outcome: "ok",
|
|
15712
15873
|
taskId,
|
|
15713
15874
|
cursor: registry.latestTaskSeq(taskId),
|
|
15714
15875
|
events,
|
|
15715
15876
|
status,
|
|
15716
|
-
terminal: isProcessTaskTerminalStatus(status)
|
|
15877
|
+
terminal: isProcessTaskTerminalStatus(status),
|
|
15878
|
+
...hint ? { hint } : {}
|
|
15717
15879
|
};
|
|
15718
15880
|
}
|
|
15719
15881
|
function formatTaskLogsContent(result4, options) {
|
|
@@ -15875,7 +16037,11 @@ function buildReadWorkspaceParameters() {
|
|
|
15875
16037
|
properties: {
|
|
15876
16038
|
path,
|
|
15877
16039
|
lines,
|
|
15878
|
-
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
|
+
}
|
|
15879
16045
|
},
|
|
15880
16046
|
required: ["path"]
|
|
15881
16047
|
};
|
|
@@ -16200,7 +16366,7 @@ function filterDeclaredWorkspaceToolNames(args2) {
|
|
|
16200
16366
|
// packages/agent-runtime/workspacePathGuard.ts
|
|
16201
16367
|
import { constants as fsConstants } from "node:fs";
|
|
16202
16368
|
import { lstat, mkdir, open, readlink, realpath as realpath2 } from "node:fs/promises";
|
|
16203
|
-
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";
|
|
16204
16370
|
function isPathInsideRoot(root, targetPath) {
|
|
16205
16371
|
const rel = relative3(resolve3(root), resolve3(targetPath));
|
|
16206
16372
|
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute2(rel);
|
|
@@ -16223,7 +16389,7 @@ async function realpathAllowMissing(targetPath) {
|
|
|
16223
16389
|
if (!isNotFoundError(error)) return null;
|
|
16224
16390
|
const parent = dirname(current);
|
|
16225
16391
|
if (parent === current) return null;
|
|
16226
|
-
tail.push(
|
|
16392
|
+
tail.push(basename3(current));
|
|
16227
16393
|
current = parent;
|
|
16228
16394
|
}
|
|
16229
16395
|
}
|
|
@@ -16417,7 +16583,7 @@ async function createMissingDirectoryChain(guard) {
|
|
|
16417
16583
|
}
|
|
16418
16584
|
try {
|
|
16419
16585
|
for (const target of missing.slice().reverse()) {
|
|
16420
|
-
const name =
|
|
16586
|
+
const name = basename3(target);
|
|
16421
16587
|
if (!name || name === "." || name === "..") {
|
|
16422
16588
|
throw workspacePathGuardError({
|
|
16423
16589
|
ok: false,
|
|
@@ -16661,6 +16827,9 @@ function describeRejectedArgValue(value) {
|
|
|
16661
16827
|
if (Array.isArray(value)) return "an array";
|
|
16662
16828
|
return `a value of type ${typeof value}`;
|
|
16663
16829
|
}
|
|
16830
|
+
function clipMarkerValue(text2, max4 = 60) {
|
|
16831
|
+
return text2.length <= max4 ? text2 : `${text2.slice(0, max4)}\u2026(${text2.length} chars)`;
|
|
16832
|
+
}
|
|
16664
16833
|
function readIntegerArg(args2) {
|
|
16665
16834
|
if (isAbsentArg(args2.value)) return {};
|
|
16666
16835
|
const min4 = args2.min ?? 1;
|
|
@@ -16719,16 +16888,16 @@ function parseLinesArg(value) {
|
|
|
16719
16888
|
}
|
|
16720
16889
|
function readFileSliceArgs(args2) {
|
|
16721
16890
|
const warnings = [];
|
|
16722
|
-
const withFallback = (slice2) => {
|
|
16891
|
+
const withFallback = (slice2, invalidLines) => {
|
|
16723
16892
|
warnings.push(
|
|
16724
16893
|
`No usable line range remained; returned the first ${READ_FILE_SLICE_FALLBACK_LINES} lines instead of the whole file.`
|
|
16725
16894
|
);
|
|
16726
|
-
return { ...slice2, maxLines: READ_FILE_SLICE_FALLBACK_LINES, warnings };
|
|
16895
|
+
return { ...slice2, maxLines: READ_FILE_SLICE_FALLBACK_LINES, warnings, invalidLines };
|
|
16727
16896
|
};
|
|
16728
|
-
if (isAbsentArg(args2.lines)) return { warnings };
|
|
16897
|
+
if (isAbsentArg(args2.lines)) return { warnings, invalidLines: void 0 };
|
|
16729
16898
|
const { slice, warning } = parseLinesArg(args2.lines);
|
|
16730
16899
|
if (warning) warnings.push(warning);
|
|
16731
|
-
return slice ? { ...slice, warnings } : withFallback({});
|
|
16900
|
+
return slice ? { ...slice, warnings, invalidLines: void 0 } : withFallback({}, describeRejectedArgValue(args2.lines));
|
|
16732
16901
|
}
|
|
16733
16902
|
function buildReadFileSliceHint(totalLines) {
|
|
16734
16903
|
return `File has ${totalLines} lines. Use lines: ${LINES_ARG_SYNTAX}, or omit it for the whole file.`;
|
|
@@ -16997,7 +17166,7 @@ var READ_FILE_LEDGER_MAX_KEYS = 256;
|
|
|
16997
17166
|
async function readFileTool(args2) {
|
|
16998
17167
|
const parsed = parseWorkspaceToolArguments(args2.call.arguments);
|
|
16999
17168
|
const requestedPath = requireWorkspaceToolPath(parsed);
|
|
17000
|
-
const { warnings, ...sliceArgs } = readFileSliceArgs(parsed);
|
|
17169
|
+
const { warnings, invalidLines, ...sliceArgs } = readFileSliceArgs(parsed);
|
|
17001
17170
|
const approval = await resolveLocalWorkspaceToolApproval({
|
|
17002
17171
|
workspaceRoot: args2.workspaceRoot,
|
|
17003
17172
|
requestedPath,
|
|
@@ -17005,7 +17174,9 @@ async function readFileTool(args2) {
|
|
|
17005
17174
|
...args2.confirmExternalFileAccess ? { confirmExternalFileAccess: args2.confirmExternalFileAccess } : {}
|
|
17006
17175
|
});
|
|
17007
17176
|
const absolutePath = approval.path;
|
|
17008
|
-
const
|
|
17177
|
+
const originalContent = await readGuardApprovedFile(approval);
|
|
17178
|
+
const projection = projectRunResultRead(absolutePath, originalContent, parsed.raw === true);
|
|
17179
|
+
const content = projection.content;
|
|
17009
17180
|
const activity = extractActivity(parsed);
|
|
17010
17181
|
const sliced = sliceReadFileContent({
|
|
17011
17182
|
content,
|
|
@@ -17015,7 +17186,16 @@ async function readFileTool(args2) {
|
|
|
17015
17186
|
content: sliced.content,
|
|
17016
17187
|
totalLines: sliced.totalLines
|
|
17017
17188
|
});
|
|
17018
|
-
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;
|
|
17019
17199
|
const relativePath = normalizeWorkspaceRelativePath({
|
|
17020
17200
|
workspaceRoot: resolve4(args2.workspaceRoot),
|
|
17021
17201
|
targetPath: absolutePath
|
|
@@ -17023,7 +17203,7 @@ async function readFileTool(args2) {
|
|
|
17023
17203
|
const force = parsed.force === true;
|
|
17024
17204
|
const ledger = args2.readLedger;
|
|
17025
17205
|
const requestRange = { startLine: sliced.startLine, endLine: sliced.endLine };
|
|
17026
|
-
const fingerprint = createHash3("sha1").update(
|
|
17206
|
+
const fingerprint = createHash3("sha1").update(originalContent).update(parsed.raw === true ? "\0raw" : "\0default").digest("hex").slice(0, 20);
|
|
17027
17207
|
let entry = ledger?.get(relativePath);
|
|
17028
17208
|
if (entry && entry.fingerprint !== fingerprint) {
|
|
17029
17209
|
entry = void 0;
|
|
@@ -17051,20 +17231,25 @@ async function readFileTool(args2) {
|
|
|
17051
17231
|
}
|
|
17052
17232
|
const metadata = {
|
|
17053
17233
|
path: relativePath,
|
|
17054
|
-
bytes: Buffer.byteLength(
|
|
17055
|
-
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
|
+
} : {},
|
|
17056
17241
|
startLine: sliced.startLine,
|
|
17057
17242
|
endLine: sliced.endLine,
|
|
17058
17243
|
totalLines: sliced.totalLines,
|
|
17059
17244
|
truncated: isTruncated,
|
|
17060
|
-
...
|
|
17245
|
+
...truncatedByCharLimit ? { truncatedByByteLimit: true, truncatedByCharLimit: true } : {},
|
|
17061
17246
|
...sliceArgs.maxLines ? { maxLines: sliceArgs.maxLines } : {},
|
|
17062
17247
|
...sliceArgs.tailLines ? { tailLines: sliceArgs.tailLines } : {},
|
|
17063
17248
|
...warnings.length ? { warnings: [...warnings, buildReadFileSliceHint(sliced.totalLines)] } : {},
|
|
17064
17249
|
...activity ? { activity } : {}
|
|
17065
17250
|
};
|
|
17066
17251
|
if (!isTruncated && ledger) {
|
|
17067
|
-
const persistedChars =
|
|
17252
|
+
const persistedChars = finalContent.length + "\n\n[tool metadata]\n".length + JSON.stringify(metadata).length;
|
|
17068
17253
|
const records = entry?.records ?? [];
|
|
17069
17254
|
records.push({ ...requestRange, chars: persistedChars });
|
|
17070
17255
|
ledger.delete(relativePath);
|
|
@@ -17078,7 +17263,7 @@ async function readFileTool(args2) {
|
|
|
17078
17263
|
ledger.delete(oldestKey);
|
|
17079
17264
|
}
|
|
17080
17265
|
}
|
|
17081
|
-
return { content:
|
|
17266
|
+
return { content: finalContent, metadata };
|
|
17082
17267
|
}
|
|
17083
17268
|
async function ensureGuardedParentDirectory(args2) {
|
|
17084
17269
|
const directoryGuard = await resolveWorkspaceSafePath({
|
|
@@ -17977,7 +18162,8 @@ function createLocalWorkspaceToolExecutors(args2) {
|
|
|
17977
18162
|
if (!Array.isArray(paths) || paths.length === 0 || paths.some((path) => typeof path !== "string" || !path.trim())) {
|
|
17978
18163
|
throw new Error("read_image: paths must contain 1 to 4 non-empty string paths (maximum 4 images)");
|
|
17979
18164
|
}
|
|
17980
|
-
const
|
|
18165
|
+
const imagePaths = paths.filter((path) => typeof path === "string");
|
|
18166
|
+
const results2 = await Promise.all(imagePaths.map(async (path) => {
|
|
17981
18167
|
try {
|
|
17982
18168
|
const absolutePath = await resolveLocalWorkspaceToolPath({
|
|
17983
18169
|
workspaceRoot: args2.workspaceRoot,
|
|
@@ -18224,6 +18410,13 @@ function getAgentRuntimeToolParametersIndex() {
|
|
|
18224
18410
|
}
|
|
18225
18411
|
|
|
18226
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
|
+
}
|
|
18227
18420
|
var NEVER_LOCAL_TOOLS = /* @__PURE__ */ new Set([
|
|
18228
18421
|
"deleteSpaces",
|
|
18229
18422
|
"updateAgent",
|
|
@@ -18337,12 +18530,13 @@ async function runExecShellGates(args2) {
|
|
|
18337
18530
|
return { kind: "pass", opts };
|
|
18338
18531
|
}
|
|
18339
18532
|
if (args2.execShellApproval) {
|
|
18340
|
-
const
|
|
18533
|
+
const execute = () => invokeCapability("execShell", args2.callArguments, {
|
|
18341
18534
|
...opts,
|
|
18342
18535
|
workspaceRoot: args2.workspaceRoot,
|
|
18343
18536
|
commandOutputLimit: args2.commandOutputLimit,
|
|
18344
18537
|
execShellApproval: args2.execShellApproval
|
|
18345
18538
|
});
|
|
18539
|
+
const result4 = await (args2.shellLifecycle ? args2.shellLifecycle(execute, args2.abortSignal) : execute());
|
|
18346
18540
|
return { kind: "handled", result: result4 };
|
|
18347
18541
|
}
|
|
18348
18542
|
let parsedInput = args2.callArguments;
|
|
@@ -18386,6 +18580,7 @@ async function executeLocalToolWithPolicy(args2) {
|
|
|
18386
18580
|
const gate = await runExecShellGates({
|
|
18387
18581
|
toolName: decision.toolName,
|
|
18388
18582
|
callArguments: args2.call.arguments,
|
|
18583
|
+
shellLifecycle: getLocalShellLifecycle(executor),
|
|
18389
18584
|
execShellApproval: args2.execShellApproval,
|
|
18390
18585
|
workspaceRoot: args2.workspaceRoot,
|
|
18391
18586
|
commandOutputLimit: args2.commandOutputLimit,
|
|
@@ -18406,7 +18601,41 @@ async function executeLocalToolWithPolicy(args2) {
|
|
|
18406
18601
|
);
|
|
18407
18602
|
}
|
|
18408
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
|
+
|
|
18409
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();
|
|
18410
18639
|
var LOCAL_TURN_ABORTED_CODE = "LOCAL_TURN_ABORTED";
|
|
18411
18640
|
function buildAbortedError() {
|
|
18412
18641
|
const error = new Error("local agent turn aborted by user");
|
|
@@ -18655,32 +18884,72 @@ async function executeToolCall(args2) {
|
|
|
18655
18884
|
const rawArguments = toolCall.function.arguments;
|
|
18656
18885
|
let unwrappedArguments = rawArguments;
|
|
18657
18886
|
if (typeof rawArguments === "string" && rawArguments.includes("$nolo_cred:") && input.adapter.credentialBroker) {
|
|
18658
|
-
|
|
18887
|
+
const sink = classifyCredentialRefSink(toolName);
|
|
18888
|
+
if (sink === "command") {
|
|
18659
18889
|
throw new Error(
|
|
18660
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`
|
|
18661
18891
|
);
|
|
18662
18892
|
}
|
|
18663
|
-
|
|
18664
|
-
|
|
18665
|
-
|
|
18666
|
-
|
|
18667
|
-
|
|
18668
|
-
|
|
18669
|
-
|
|
18670
|
-
|
|
18671
|
-
|
|
18672
|
-
|
|
18673
|
-
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
18682
|
-
|
|
18683
|
-
|
|
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
|
+
}
|
|
18684
18953
|
}
|
|
18685
18954
|
if (tailDropNotice) {
|
|
18686
18955
|
toolResult = {
|
|
@@ -18695,6 +18964,15 @@ ${toolResult.content}` : toolResult.content,
|
|
|
18695
18964
|
toolCallId: toolCall.id,
|
|
18696
18965
|
metadata: toolResult.metadata
|
|
18697
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
|
+
}
|
|
18698
18976
|
if (actionGate && input.onActionGate) {
|
|
18699
18977
|
const replacement = await runAbortableToolTask(input, input.onActionGate(actionGate), `${toolName} action gate`);
|
|
18700
18978
|
if (replacement) {
|
|
@@ -18788,10 +19066,15 @@ function applyPersistedTurnInput(messages, persistedInput, persistedInputReferen
|
|
|
18788
19066
|
}
|
|
18789
19067
|
function createTurnTranscript(args2) {
|
|
18790
19068
|
let working = args2.initialWorking;
|
|
18791
|
-
|
|
19069
|
+
let raw = args2.initialWorking.slice(
|
|
18792
19070
|
args2.prefixCount + args2.historyCount
|
|
18793
19071
|
);
|
|
18794
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
|
+
}
|
|
18795
19078
|
return {
|
|
18796
19079
|
working: () => working,
|
|
18797
19080
|
replaceWorkingHistory: (nextWorkingView) => {
|
|
@@ -18810,7 +19093,13 @@ function createTurnTranscript(args2) {
|
|
|
18810
19093
|
raw.pop();
|
|
18811
19094
|
return working.pop();
|
|
18812
19095
|
},
|
|
18813
|
-
|
|
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
|
+
}
|
|
18814
19103
|
};
|
|
18815
19104
|
}
|
|
18816
19105
|
|
|
@@ -18862,10 +19151,10 @@ function createTurnUsageLedger(args2) {
|
|
|
18862
19151
|
recordProviderCall: ({ usage, model, provider, telemetry }) => {
|
|
18863
19152
|
turnUsage = mergeTurnUsage(turnUsage, usage);
|
|
18864
19153
|
lastContextUsage = usage;
|
|
18865
|
-
if (usage && Object.keys(usage).length > 0) {
|
|
19154
|
+
if (usage && Object.keys(usage).length > 0 || telemetry?.requestState) {
|
|
18866
19155
|
providerRecords.push({
|
|
18867
|
-
callId: resolveRecordCallId(usage),
|
|
18868
|
-
usage,
|
|
19156
|
+
callId: resolveRecordCallId(usage ?? {}),
|
|
19157
|
+
usage: usage ?? {},
|
|
18869
19158
|
model: model || args2.model || "unknown",
|
|
18870
19159
|
...provider || args2.provider ? { provider: provider || args2.provider } : {},
|
|
18871
19160
|
...telemetry && Object.keys(telemetry).length > 0 ? { telemetry } : {},
|
|
@@ -18896,7 +19185,42 @@ function createTurnUsageLedger(args2) {
|
|
|
18896
19185
|
}
|
|
18897
19186
|
|
|
18898
19187
|
// packages/agent-runtime/leafFinalHandoff.ts
|
|
18899
|
-
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
|
+
}
|
|
18900
19224
|
|
|
18901
19225
|
// packages/agent-runtime/contextBlockScope.ts
|
|
18902
19226
|
var isContextBlockScope = (value) => {
|
|
@@ -18912,6 +19236,34 @@ var normalizeContextBlockScopes = (legacyBlocks = void 0, scopes = void 0) => {
|
|
|
18912
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" }));
|
|
18913
19237
|
};
|
|
18914
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
|
+
|
|
18915
19267
|
// packages/agent-runtime/localAutoCompaction.ts
|
|
18916
19268
|
import { randomUUID } from "node:crypto";
|
|
18917
19269
|
function toPlanCompressionMessages(history) {
|
|
@@ -18919,6 +19271,7 @@ function toPlanCompressionMessages(history) {
|
|
|
18919
19271
|
id: typeof message.id === "string" && message.id.length > 0 ? message.id : `local-${index}`,
|
|
18920
19272
|
role: message.role,
|
|
18921
19273
|
content: message.content ?? "",
|
|
19274
|
+
...typeof message.tool_call_id === "string" ? { tool_call_id: message.tool_call_id } : {},
|
|
18922
19275
|
...Array.isArray(message.tool_calls) ? { tool_calls: message.tool_calls } : {}
|
|
18923
19276
|
}));
|
|
18924
19277
|
}
|
|
@@ -18936,9 +19289,10 @@ function hashSummarySourceSlice(history, summarizedBeforeId) {
|
|
|
18936
19289
|
const found = findSummaryAnchorIndex(bridged, summarizedBeforeId);
|
|
18937
19290
|
if (found === -1) return void 0;
|
|
18938
19291
|
const slice = bridged.slice(0, found + 1).map((message, index) => ({
|
|
18939
|
-
...message,
|
|
18940
19292
|
id: `local-${index}`,
|
|
18941
|
-
|
|
19293
|
+
role: message.role,
|
|
19294
|
+
content: message.content ?? "",
|
|
19295
|
+
...Array.isArray(message.tool_calls) ? { tool_calls: message.tool_calls } : {}
|
|
18942
19296
|
}));
|
|
18943
19297
|
return sha256Hex(JSON.stringify(slice));
|
|
18944
19298
|
}
|
|
@@ -18976,37 +19330,87 @@ function projectHistoryWithSummary(args2) {
|
|
|
18976
19330
|
if (found !== -1) startIndex = found + 1;
|
|
18977
19331
|
}
|
|
18978
19332
|
const projected = args2.history.slice(startIndex);
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
for (let i = history.length - 1; i >= 0; i -= 1) {
|
|
18985
|
-
const at = history[i]?.createdAt;
|
|
18986
|
-
if (typeof at === "number" && Number.isFinite(at)) {
|
|
18987
|
-
return nowMs - at > COLD_RESUME_IDLE_MS;
|
|
19333
|
+
let latestUser = -1;
|
|
19334
|
+
for (let i = args2.history.length - 1; i >= 0; i--) {
|
|
19335
|
+
if (args2.history[i].role === "user") {
|
|
19336
|
+
latestUser = i;
|
|
19337
|
+
break;
|
|
18988
19338
|
}
|
|
18989
19339
|
}
|
|
18990
|
-
|
|
19340
|
+
const preservedUser = latestUser >= 0 && latestUser < startIndex ? [args2.history[latestUser]] : [];
|
|
19341
|
+
const summaryMsg = args2.summary.trim().length > 0 ? [buildLocalSummaryHistoryMessage(args2.summary)] : [];
|
|
19342
|
+
return [...summaryMsg, ...preservedUser, ...projected];
|
|
18991
19343
|
}
|
|
18992
|
-
|
|
19344
|
+
var COLD_RESUME_IDLE_MS = 60 * 60 * 1e3;
|
|
19345
|
+
async function completeRoutedCompactionSummary(args2) {
|
|
19346
|
+
const budget = createSummaryBudget({ mode: "automatic", signal: args2.options.signal, deadlineMs: args2.options.deadlineMs });
|
|
18993
19347
|
try {
|
|
18994
|
-
const
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
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
|
+
}
|
|
19356
|
+
});
|
|
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
|
+
} }
|
|
19002
19376
|
});
|
|
19003
|
-
|
|
19004
|
-
|
|
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();
|
|
19005
19403
|
}
|
|
19006
19404
|
}
|
|
19007
19405
|
var COMPACTION_RETRY_BACKOFF_MS = 6e4;
|
|
19008
19406
|
var COMPACTION_RETRY_BACKOFF_MAX_ENTRIES = 256;
|
|
19009
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
|
+
}
|
|
19010
19414
|
function isCompactionBackedOff(dialogId, now) {
|
|
19011
19415
|
for (const [key, until2] of compactionRetryBackoff) {
|
|
19012
19416
|
if (until2 <= now) compactionRetryBackoff.delete(key);
|
|
@@ -19076,7 +19480,19 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19076
19480
|
reason = "hash-mismatch";
|
|
19077
19481
|
}
|
|
19078
19482
|
console.warn(
|
|
19079
|
-
`[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
|
+
}
|
|
19080
19496
|
);
|
|
19081
19497
|
stored = null;
|
|
19082
19498
|
}
|
|
@@ -19085,19 +19501,34 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19085
19501
|
const legacyAnchorIndex = summarizedBeforeId ? findSummaryAnchorIndex(bridged, summarizedBeforeId) : -1;
|
|
19086
19502
|
const planAnchorId = summarizedBeforeId && /^local-(0|[1-9]\d*)$/.test(summarizedBeforeId) && legacyAnchorIndex >= 0 ? bridged[legacyAnchorIndex].id : summarizedBeforeId;
|
|
19087
19503
|
const contextWindow = typeof args2.contextWindow === "number" && Number.isFinite(args2.contextWindow) && args2.contextWindow > 0 ? args2.contextWindow : getModelContextWindow(args2.model ?? "");
|
|
19088
|
-
const allMsgs = toPlanCompressionMessages(history);
|
|
19089
|
-
const
|
|
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;
|
|
19090
19509
|
const plan = planCompression({
|
|
19091
19510
|
allMsgs,
|
|
19092
19511
|
summarizedBeforeId: planAnchorId,
|
|
19093
19512
|
summary: existingSummary,
|
|
19094
19513
|
contextWindow,
|
|
19095
|
-
|
|
19514
|
+
// 失败路径补救:预算裁剪即将丢消息时由 localLoop 传入 force,交由 planCompression
|
|
19515
|
+
// 的既有 force 语义产出待压缩切片(仍受最小条数/安全前缀约束)。
|
|
19516
|
+
force,
|
|
19517
|
+
...force ? { reason: "budget_rescue" } : {},
|
|
19518
|
+
availableHistoryTokens: args2.availableHistoryTokens,
|
|
19519
|
+
preserveLatestUserByProjection: true,
|
|
19520
|
+
maxInputItems,
|
|
19096
19521
|
...args2.realContextUsagePercent !== void 0 ? { realContextUsagePercent: args2.realContextUsagePercent } : {}
|
|
19097
19522
|
});
|
|
19523
|
+
const itemDiagnostics = maxInputItems !== void 0 ? {
|
|
19524
|
+
itemCount: plan.diagnostics?.itemCount,
|
|
19525
|
+
maxInputItems,
|
|
19526
|
+
triggeredByItemLimit: plan.diagnostics?.triggeredByItemLimit
|
|
19527
|
+
} : {};
|
|
19098
19528
|
const projectExisting = () => {
|
|
19099
19529
|
const diag = plan.diagnostics;
|
|
19100
19530
|
const diagSnapshot = diag ? {
|
|
19531
|
+
...itemDiagnostics,
|
|
19101
19532
|
estimatedTokens: diag.totalUsed,
|
|
19102
19533
|
historyBudget: diag.historyBudget,
|
|
19103
19534
|
triggerRatio: diag.triggerRatio,
|
|
@@ -19105,7 +19536,7 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19105
19536
|
} : {};
|
|
19106
19537
|
const skippedDecision = {
|
|
19107
19538
|
outcome: "skipped",
|
|
19108
|
-
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",
|
|
19109
19540
|
...diagSnapshot,
|
|
19110
19541
|
...diag ? { pendingMsgCount: diag.pendingMsgCount } : {},
|
|
19111
19542
|
...diag?.compressCount !== void 0 ? { compressCount: diag.compressCount } : {}
|
|
@@ -19119,6 +19550,13 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19119
19550
|
}),
|
|
19120
19551
|
compressed: true,
|
|
19121
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
|
+
},
|
|
19122
19560
|
decision: {
|
|
19123
19561
|
outcome: "compressed",
|
|
19124
19562
|
trigger: "existing-summary",
|
|
@@ -19139,6 +19577,7 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19139
19577
|
outcome: "skipped",
|
|
19140
19578
|
skipReason: "retry-backoff",
|
|
19141
19579
|
...diag ? {
|
|
19580
|
+
...itemDiagnostics,
|
|
19142
19581
|
estimatedTokens: diag.totalUsed,
|
|
19143
19582
|
historyBudget: diag.historyBudget,
|
|
19144
19583
|
triggerRatio: diag.triggerRatio,
|
|
@@ -19147,17 +19586,48 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19147
19586
|
}
|
|
19148
19587
|
};
|
|
19149
19588
|
}
|
|
19150
|
-
|
|
19151
|
-
const
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19589
|
+
const msgsToCompress = plan.msgsToCompress;
|
|
19590
|
+
const bounded3 = buildBoundedCompactionRequest({
|
|
19591
|
+
msgsToCompress,
|
|
19592
|
+
previousSummary: existingSummary,
|
|
19593
|
+
contextWindow,
|
|
19594
|
+
canonicalizeToolName
|
|
19595
|
+
});
|
|
19596
|
+
if (bounded3.status === "blocked") {
|
|
19597
|
+
const detail = `bounded compaction blocked: ${bounded3.reason}`;
|
|
19598
|
+
console.warn(
|
|
19599
|
+
`[localLoop] ${detail}`,
|
|
19600
|
+
...bounded3.diagnostics ? [bounded3.diagnostics] : []
|
|
19601
|
+
);
|
|
19602
|
+
return {
|
|
19603
|
+
...projectExisting(),
|
|
19604
|
+
decision: { outcome: "skipped", skipReason: "bounded-request-blocked", detail }
|
|
19605
|
+
};
|
|
19606
|
+
}
|
|
19607
|
+
emitPhase({ kind: "compaction-start" });
|
|
19608
|
+
let compactionAttemptId = randomUUID();
|
|
19609
|
+
const maxAttempts = 3;
|
|
19610
|
+
let attempt = 0;
|
|
19611
|
+
let retryCount = 0;
|
|
19612
|
+
let attemptRoute = "current";
|
|
19613
|
+
let attemptTimingLogged = false;
|
|
19614
|
+
let compactionT0 = Date.now();
|
|
19615
|
+
let compactionInputTokens;
|
|
19616
|
+
let compactionPrevSummaryTokens;
|
|
19617
|
+
let compactionInputSource;
|
|
19618
|
+
let compactionPrevSummarySource;
|
|
19619
|
+
let primaryElapsedMs;
|
|
19158
19620
|
let fallbackElapsedMs;
|
|
19159
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
|
+
};
|
|
19160
19628
|
const logCompactionTiming = (outcome, fields) => {
|
|
19629
|
+
if (attemptTimingLogged) return;
|
|
19630
|
+
attemptTimingLogged = true;
|
|
19161
19631
|
if (compactionInputTokens === void 0 && compactionInputSource !== void 0) {
|
|
19162
19632
|
compactionInputTokens = estimateTokenCount(compactionInputSource);
|
|
19163
19633
|
}
|
|
@@ -19167,10 +19637,20 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19167
19637
|
console.log(
|
|
19168
19638
|
`[compaction-timing] ${JSON.stringify({
|
|
19169
19639
|
attemptId: compactionAttemptId,
|
|
19170
|
-
|
|
19640
|
+
attempt,
|
|
19641
|
+
maxAttempts,
|
|
19642
|
+
physicalAttempts: attempt,
|
|
19643
|
+
route: attemptRoute,
|
|
19644
|
+
model: fields.model ?? summaryModel ?? null,
|
|
19645
|
+
provider: summaryProvider ?? null,
|
|
19171
19646
|
inputTokens: compactionInputTokens ?? null,
|
|
19172
19647
|
prevSummaryTokens: compactionPrevSummaryTokens ?? null,
|
|
19173
|
-
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,
|
|
19174
19654
|
elapsedMs: Date.now() - compactionT0,
|
|
19175
19655
|
primaryElapsedMs: primaryElapsedMs ?? null,
|
|
19176
19656
|
fallbackElapsedMs: fallbackElapsedMs ?? null,
|
|
@@ -19180,57 +19660,153 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19180
19660
|
);
|
|
19181
19661
|
};
|
|
19182
19662
|
try {
|
|
19663
|
+
let reportAttemptUsage2 = function(value) {
|
|
19664
|
+
const usage = value?.usage;
|
|
19665
|
+
if (usage && typeof usage === "object") args2.onAttemptUsage?.(usage);
|
|
19666
|
+
};
|
|
19667
|
+
var reportAttemptUsage = reportAttemptUsage2;
|
|
19183
19668
|
if (args2.abortSignal?.aborted) {
|
|
19184
19669
|
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
19185
19670
|
}
|
|
19186
|
-
const
|
|
19187
|
-
if (args2.abortSignal?.aborted) {
|
|
19188
|
-
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
19189
|
-
}
|
|
19190
|
-
const msgsToCompress = plan.msgsToCompress;
|
|
19191
|
-
const messagesText = formatMessagesForSummaryWithTruncation(
|
|
19192
|
-
msgsToCompress,
|
|
19193
|
-
TOOL_RESULT_TRUNCATE_CHARS,
|
|
19194
|
-
computeSummaryInputTokenCap(contextWindow)
|
|
19195
|
-
);
|
|
19196
|
-
const fileOpsText = formatFileOperationsFromMessages(
|
|
19197
|
-
msgsToCompress,
|
|
19198
|
-
canonicalizeToolName
|
|
19199
|
-
);
|
|
19200
|
-
const promptContent = buildCompactionUserContent({
|
|
19201
|
-
previousSummary: existingSummary,
|
|
19202
|
-
messagesText,
|
|
19203
|
-
fileOpsText
|
|
19204
|
-
});
|
|
19671
|
+
const promptContent = bounded3.promptContent;
|
|
19205
19672
|
emitPhase({ kind: "waiting-provider" });
|
|
19206
|
-
compactionInputSource =
|
|
19673
|
+
compactionInputSource = promptContent;
|
|
19207
19674
|
compactionPrevSummarySource = existingSummary;
|
|
19208
19675
|
compactionT0 = Date.now();
|
|
19209
|
-
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;
|
|
19210
19679
|
const requestController = new AbortController();
|
|
19211
19680
|
let timeoutHandle;
|
|
19212
19681
|
let abortListener;
|
|
19213
19682
|
if (args2.abortSignal?.aborted) requestController.abort(args2.abortSignal.reason);
|
|
19214
|
-
|
|
19215
|
-
|
|
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
|
+
},
|
|
19216
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: {
|
|
19217
19764
|
signal: requestController.signal,
|
|
19218
|
-
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
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(
|
|
19227
19803
|
(value) => ({ kind: "done", value }),
|
|
19228
19804
|
(error) => ({ kind: "provider-error", error })
|
|
19229
19805
|
);
|
|
19230
19806
|
const guards = [];
|
|
19231
19807
|
if (timeoutMs) guards.push(new Promise((resolve6) => {
|
|
19232
19808
|
timeoutHandle = setTimeout(() => {
|
|
19233
|
-
requestController.abort();
|
|
19809
|
+
requestController.abort(new DOMException("Summary deadline exceeded", "TimeoutError"));
|
|
19234
19810
|
resolve6({ kind: "timeout" });
|
|
19235
19811
|
}, timeoutMs);
|
|
19236
19812
|
}));
|
|
@@ -19247,80 +19823,123 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19247
19823
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
19248
19824
|
if (abortListener) args2.abortSignal?.removeEventListener("abort", abortListener);
|
|
19249
19825
|
const result4 = outcome.kind === "done" ? outcome.value : void 0;
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
if (
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
});
|
|
19275
|
-
}
|
|
19276
|
-
if (fallbackResult.summary) {
|
|
19277
|
-
newSummary = fallbackResult.summary;
|
|
19278
|
-
} else {
|
|
19279
|
-
fallbackFailureDetail = fallbackResult.error ?? "no summary";
|
|
19280
|
-
}
|
|
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 };
|
|
19281
19850
|
}
|
|
19851
|
+
const newSummary = result4?.content?.trim() ?? "";
|
|
19282
19852
|
if (!newSummary) {
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
|
|
19288
|
-
|
|
19289
|
-
|
|
19290
|
-
|
|
19291
|
-
|
|
19292
|
-
|
|
19293
|
-
|
|
19294
|
-
|
|
19295
|
-
|
|
19296
|
-
|
|
19297
|
-
|
|
19298
|
-
|
|
19299
|
-
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
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 } };
|
|
19857
|
+
}
|
|
19858
|
+
const metricsReason = invalidSummary ? "invalid_summary" : "context_budget";
|
|
19859
|
+
const metrics = buildCompactionMetricsFromPlan({
|
|
19860
|
+
reason: metricsReason,
|
|
19861
|
+
previousSummary: existingSummary,
|
|
19862
|
+
plan: {
|
|
19863
|
+
msgsToCompress: bounded3.coveredMessages,
|
|
19864
|
+
msgsToKeep: [...msgsToCompress.slice(bounded3.coveredMessages.length), ...plan.msgsToKeep]
|
|
19865
|
+
},
|
|
19866
|
+
newSummary,
|
|
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
|
|
19307
19877
|
}
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19878
|
+
});
|
|
19879
|
+
const projectedHistory = projectHistoryWithSummary({
|
|
19880
|
+
history,
|
|
19881
|
+
summary: newSummary,
|
|
19882
|
+
summarizedBeforeId: bounded3.summarizedBeforeId
|
|
19883
|
+
});
|
|
19884
|
+
const projectedMessages = toPlanCompressionMessages(prepareHistoryForNextTurn(projectedHistory, args2.contextReferenceResolver));
|
|
19885
|
+
const projectedTokens = projectedMessages.reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0);
|
|
19886
|
+
const projectedRetained = projectedMessages.slice(1);
|
|
19887
|
+
metrics.retainedTokens = projectedRetained.reduce((sum2, message) => sum2 + getMessageTokenCount(message), 0);
|
|
19888
|
+
metrics.retainedCount = projectedRetained.length;
|
|
19889
|
+
const { effectiveRawMessageBudget } = resolveEffectiveCompactionBudgets({
|
|
19890
|
+
contextWindow,
|
|
19891
|
+
triggerRatio: plan.diagnostics.triggerRatio,
|
|
19892
|
+
historyBudget: contextWindow,
|
|
19893
|
+
rawMessageBudget: contextWindow,
|
|
19894
|
+
summaryTokens: 0,
|
|
19895
|
+
newSummaryTokenReserve: estimateTokenCount(newSummary)
|
|
19896
|
+
});
|
|
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));
|
|
19900
|
+
if (!withinSafetyBudget) {
|
|
19901
|
+
console.warn("[localLoop] compaction projection remains above safety budget", {
|
|
19902
|
+
projectedTokens,
|
|
19903
|
+
effectiveHistoryBudget,
|
|
19904
|
+
...maxInputItems !== void 0 ? { projectedItemCount, maxInputItems } : {}
|
|
19313
19905
|
});
|
|
19314
19906
|
}
|
|
19907
|
+
const oldProjection = projectExisting();
|
|
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) {
|
|
19912
|
+
const failureMessage = `compaction candidate rejected: ${projectedTokens >= beforeProjectedTokens ? "no token reduction" : "above history budget"} (before=${beforeProjectedTokens}, after=${projectedTokens}, budget=${historyBudget})`;
|
|
19913
|
+
console.warn(`[localLoop] ${failureMessage}`);
|
|
19914
|
+
recordCompactionFailure(dialogId, args2.now?.() ?? Date.now());
|
|
19915
|
+
logCompactionTiming("empty", {});
|
|
19916
|
+
emitPhase({ kind: "compaction-end" });
|
|
19917
|
+
return {
|
|
19918
|
+
...oldProjection,
|
|
19919
|
+
failureMessage,
|
|
19920
|
+
...result4?.usage ? { usage: result4.usage } : {},
|
|
19921
|
+
decision: {
|
|
19922
|
+
outcome: "skipped",
|
|
19923
|
+
skipReason: "unsafe-projection",
|
|
19924
|
+
detail: failureMessage,
|
|
19925
|
+
...itemDiagnostics,
|
|
19926
|
+
...maxInputItems !== void 0 ? { projectedItemCount } : {}
|
|
19927
|
+
}
|
|
19928
|
+
};
|
|
19929
|
+
}
|
|
19315
19930
|
const sourceMeta = await computeSummarySourceMetadata(
|
|
19316
19931
|
toPlanCompressionMessages(history),
|
|
19317
|
-
|
|
19932
|
+
bounded3.summarizedBeforeId
|
|
19318
19933
|
);
|
|
19934
|
+
if (Date.now() >= summaryDeadlineMs) throw Object.assign(new Error("Summary deadline exceeded"), { compactionReason: "timeout" });
|
|
19935
|
+
if (args2.abortSignal?.aborted) {
|
|
19936
|
+
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
19937
|
+
}
|
|
19319
19938
|
const saveT0 = Date.now();
|
|
19320
19939
|
await adapter.saveDialogSummary({
|
|
19321
19940
|
dialogId,
|
|
19322
19941
|
summary: newSummary,
|
|
19323
|
-
summarizedBeforeId:
|
|
19942
|
+
summarizedBeforeId: bounded3.summarizedBeforeId,
|
|
19324
19943
|
// 内容寻址失效检测:存锚点切片哈希与长度,供下轮载入校验。
|
|
19325
19944
|
sourceHash: sourceMeta?.sourceHash,
|
|
19326
19945
|
sourceCount: sourceMeta?.sourceCount ?? 0,
|
|
@@ -19332,14 +19951,6 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19332
19951
|
)
|
|
19333
19952
|
});
|
|
19334
19953
|
saveElapsedMs = Date.now() - saveT0;
|
|
19335
|
-
const metricsReason = invalidSummary ? "invalid_summary" : coldResume ? "cold_resume" : "context_budget";
|
|
19336
|
-
const metrics = buildCompactionMetricsFromPlan({
|
|
19337
|
-
reason: metricsReason,
|
|
19338
|
-
previousSummary: existingSummary,
|
|
19339
|
-
plan,
|
|
19340
|
-
newSummary,
|
|
19341
|
-
summaryUsage: result4?.usage
|
|
19342
|
-
});
|
|
19343
19954
|
console.log(formatCompactionMetricsLog(metrics));
|
|
19344
19955
|
logCompactionTiming("success", {
|
|
19345
19956
|
model: result4?.model ?? args2.model ?? null,
|
|
@@ -19347,21 +19958,27 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19347
19958
|
});
|
|
19348
19959
|
emitPhase({ kind: "compaction-end" });
|
|
19349
19960
|
return {
|
|
19350
|
-
history:
|
|
19351
|
-
history,
|
|
19352
|
-
summary: newSummary,
|
|
19353
|
-
summarizedBeforeId: plan.newSummarizedBeforeId
|
|
19354
|
-
}),
|
|
19961
|
+
history: projectedHistory,
|
|
19355
19962
|
compressed: true,
|
|
19356
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
|
+
},
|
|
19357
19971
|
reason: metricsReason,
|
|
19358
|
-
beforeTokens:
|
|
19359
|
-
afterTokens:
|
|
19972
|
+
beforeTokens: beforeProjectedTokens,
|
|
19973
|
+
afterTokens: projectedTokens,
|
|
19974
|
+
withinSafetyBudget,
|
|
19360
19975
|
...result4?.usage ? { usage: result4.usage } : {},
|
|
19361
19976
|
metrics,
|
|
19362
19977
|
decision: {
|
|
19363
19978
|
outcome: "compressed",
|
|
19364
|
-
trigger: invalidSummary ? "invalid-summary" :
|
|
19979
|
+
trigger: invalidSummary ? "invalid-summary" : plan.diagnostics?.triggeredByItemLimit ? "item-limit" : plan.diagnostics?.triggeredByRealUsage ? "real-usage" : "estimate",
|
|
19980
|
+
...itemDiagnostics,
|
|
19981
|
+
...maxInputItems !== void 0 ? { projectedItemCount } : {},
|
|
19365
19982
|
...plan.diagnostics ? {
|
|
19366
19983
|
estimatedTokens: plan.diagnostics.totalUsed,
|
|
19367
19984
|
historyBudget: plan.diagnostics.historyBudget,
|
|
@@ -19371,18 +19988,39 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
19371
19988
|
}
|
|
19372
19989
|
};
|
|
19373
19990
|
} catch (error) {
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
|
|
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
|
+
};
|
|
19377
20006
|
logCompactionTiming(failureReason, {});
|
|
19378
20007
|
const failureNow = args2.now?.() ?? Date.now();
|
|
19379
20008
|
if (failureReason !== "aborted") recordCompactionFailure(dialogId, failureNow);
|
|
19380
|
-
emitPhase({ kind: "compaction-
|
|
20009
|
+
if (failureReason === "aborted") emitPhase({ kind: "compaction-end" });
|
|
20010
|
+
else emitPhase({ kind: "compaction-failed", reason: failureReason });
|
|
19381
20011
|
return {
|
|
19382
20012
|
...projectExisting(),
|
|
19383
20013
|
failureMessage,
|
|
19384
20014
|
failureReason,
|
|
19385
|
-
|
|
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
|
+
}
|
|
19386
20024
|
};
|
|
19387
20025
|
}
|
|
19388
20026
|
}
|
|
@@ -19393,13 +20031,14 @@ function emitCompactionPhaseEvent(boundary, phase, scope3) {
|
|
|
19393
20031
|
emitLoopEvent(boundary, { kind: "turn-phase", phase: "compacting", atMs, compactionScope: scope3 });
|
|
19394
20032
|
emitLoopEvent(boundary, { kind: "compaction-start", atMs, scope: scope3 });
|
|
19395
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 });
|
|
19396
20035
|
else if (phase.kind === "compaction-end") emitLoopEvent(boundary, { kind: "compaction-end", atMs, scope: scope3 });
|
|
19397
20036
|
else emitLoopEvent(boundary, { kind: "compaction-failed", atMs, scope: scope3, reason: phase.reason });
|
|
19398
20037
|
}
|
|
19399
20038
|
function emitCompactionObservationEvent(boundary, compacted) {
|
|
19400
20039
|
const decision = compacted.decision;
|
|
19401
20040
|
if (decision?.outcome === "skipped") {
|
|
19402
|
-
const isProtectionGap = 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";
|
|
19403
20042
|
const approachingBudget = decision.skipReason === "below-trigger" && typeof decision.estimatedTokens === "number" && typeof decision.historyBudget === "number" && decision.historyBudget > 0 && decision.estimatedTokens >= decision.historyBudget * 0.5;
|
|
19404
20043
|
if (!isProtectionGap && !approachingBudget) return;
|
|
19405
20044
|
}
|
|
@@ -19407,15 +20046,22 @@ function emitCompactionObservationEvent(boundary, compacted) {
|
|
|
19407
20046
|
kind: "compaction",
|
|
19408
20047
|
atMs: Date.now(),
|
|
19409
20048
|
...compacted.reason ? { reason: compacted.reason } : {},
|
|
20049
|
+
...compacted.withinSafetyBudget === false ? { detail: "Projected history remains above the token or input-item safety budget" } : {},
|
|
19410
20050
|
summaryGenerated: compacted.summaryGenerated,
|
|
19411
20051
|
compressed: compacted.compressed,
|
|
19412
20052
|
...compacted.failureMessage ? { failed: true, detail: compacted.failureMessage } : {},
|
|
19413
|
-
...decision?.outcome === "skipped" ? { skipped: true, skipReason: decision.skipReason } : {},
|
|
20053
|
+
...decision?.outcome === "skipped" ? { skipped: true, skipReason: decision.skipReason, ...decision.detail ? { detail: decision.detail } : {} } : {},
|
|
19414
20054
|
...decision && "trigger" in decision && decision.trigger ? { trigger: decision.trigger } : {},
|
|
19415
20055
|
...decision && "estimatedTokens" in decision && decision.estimatedTokens !== void 0 ? { estimatedTokens: decision.estimatedTokens } : {},
|
|
19416
20056
|
...decision && "historyBudget" in decision && decision.historyBudget !== void 0 ? { historyBudget: decision.historyBudget } : {},
|
|
19417
20057
|
...decision && "realUsageRatio" in decision && decision.realUsageRatio !== void 0 ? { realUsageRatio: decision.realUsageRatio } : {},
|
|
19418
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
|
+
} : {},
|
|
19419
20065
|
...compacted.beforeTokens !== void 0 ? { beforeTokens: compacted.beforeTokens } : {},
|
|
19420
20066
|
...compacted.afterTokens !== void 0 ? { afterTokens: compacted.afterTokens } : {},
|
|
19421
20067
|
...compacted.savedTokens !== void 0 ? { savedTokens: compacted.savedTokens } : {}
|
|
@@ -19434,7 +20080,7 @@ function createTurnCompactionController(args2) {
|
|
|
19434
20080
|
}
|
|
19435
20081
|
};
|
|
19436
20082
|
const compactionDialogId = args2.continueDialogId ?? ephemeralDialogId;
|
|
19437
|
-
const
|
|
20083
|
+
const runCompaction = async (history, force) => {
|
|
19438
20084
|
let realContextUsagePercent;
|
|
19439
20085
|
if (args2.continueDialogId && typeof args2.adapter.loadLastContextUsage === "function") {
|
|
19440
20086
|
try {
|
|
@@ -19457,15 +20103,21 @@ function createTurnCompactionController(args2) {
|
|
|
19457
20103
|
adapter: args2.adapter,
|
|
19458
20104
|
dialogId: args2.continueDialogId,
|
|
19459
20105
|
history,
|
|
20106
|
+
contextReferenceResolver: args2.contextReferenceResolver,
|
|
19460
20107
|
model: args2.model,
|
|
20108
|
+
provider: args2.provider,
|
|
20109
|
+
providerEndpoint: args2.providerEndpoint,
|
|
19461
20110
|
resolveProvider: args2.resolveProvider,
|
|
19462
20111
|
contextWindow: args2.contextWindow,
|
|
19463
20112
|
realContextUsagePercent,
|
|
20113
|
+
force,
|
|
19464
20114
|
abortSignal: args2.abortSignal,
|
|
19465
20115
|
timeoutMs: args2.timeoutMs,
|
|
19466
20116
|
summaryFallback: args2.summaryFallback,
|
|
20117
|
+
onAttemptUsage: args2.onUsage,
|
|
19467
20118
|
onPhase: (phase) => emitPhase(phase, "initial")
|
|
19468
20119
|
});
|
|
20120
|
+
args2.onSelectedSummary?.(compacted.selectedSummary ?? { outcome: "absent" });
|
|
19469
20121
|
emitObservation(compacted);
|
|
19470
20122
|
return { history: compacted.history, usage: compacted.usage };
|
|
19471
20123
|
} catch (error) {
|
|
@@ -19473,11 +20125,25 @@ function createTurnCompactionController(args2) {
|
|
|
19473
20125
|
return { history };
|
|
19474
20126
|
}
|
|
19475
20127
|
};
|
|
19476
|
-
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;
|
|
19477
20136
|
const contextUsage = args2.getContextUsage();
|
|
19478
|
-
|
|
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
|
+
}
|
|
19479
20145
|
const ratio = inputTokens > 0 ? Math.min(1, inputTokens / args2.contextWindow) : void 0;
|
|
19480
|
-
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) {
|
|
19481
20147
|
return;
|
|
19482
20148
|
}
|
|
19483
20149
|
try {
|
|
@@ -19490,18 +20156,22 @@ function createTurnCompactionController(args2) {
|
|
|
19490
20156
|
// 锚点与 sourceHash 都必须按持久化形态计算——否则下轮从 store
|
|
19491
20157
|
// 重载后重算 hash 必不匹配,摘要被判无效、白付一次摘要调用。
|
|
19492
20158
|
history: args2.getCanonicalCompactionHistory(),
|
|
20159
|
+
requestOverBudget,
|
|
20160
|
+
availableHistoryTokens: availableHistoryTokens?.(),
|
|
20161
|
+
contextReferenceResolver: args2.contextReferenceResolver,
|
|
19493
20162
|
model: args2.model,
|
|
20163
|
+
provider: args2.provider,
|
|
20164
|
+
providerEndpoint: args2.providerEndpoint,
|
|
19494
20165
|
resolveProvider: args2.resolveProvider,
|
|
19495
20166
|
contextWindow: args2.contextWindow,
|
|
19496
20167
|
...ratio !== void 0 ? { realContextUsagePercent: ratio } : {},
|
|
19497
20168
|
abortSignal: args2.abortSignal,
|
|
19498
20169
|
timeoutMs: args2.timeoutMs,
|
|
19499
20170
|
summaryFallback: args2.summaryFallback,
|
|
19500
|
-
|
|
20171
|
+
onAttemptUsage: args2.onUsage,
|
|
20172
|
+
onPhase: (phase) => emitPhase(phase, initial ? "initial" : "in-loop")
|
|
19501
20173
|
});
|
|
19502
|
-
|
|
19503
|
-
args2.onUsage(compacted.usage);
|
|
19504
|
-
}
|
|
20174
|
+
lastCompactionOutcome = { result: compacted };
|
|
19505
20175
|
if (compacted.compressed) {
|
|
19506
20176
|
const rebuilt = composeProviderMessages({
|
|
19507
20177
|
prefix: args2.getWorkingPrefix(),
|
|
@@ -19516,16 +20186,65 @@ function createTurnCompactionController(args2) {
|
|
|
19516
20186
|
}
|
|
19517
20187
|
args2.replaceWorkingView(rebuilt.messages);
|
|
19518
20188
|
}
|
|
20189
|
+
if (compacted.compressed || initial) {
|
|
20190
|
+
args2.onSelectedSummary?.(compacted.selectedSummary ?? { outcome: initial ? "absent" : "unknown" });
|
|
20191
|
+
}
|
|
19519
20192
|
emitObservation(compacted);
|
|
19520
20193
|
} catch (error) {
|
|
20194
|
+
lastCompactionOutcome = { ...lastCompactionOutcome, error: classifySummaryError(error) };
|
|
19521
20195
|
console.warn("[localLoop] in-loop auto-compaction failed:", error);
|
|
19522
20196
|
}
|
|
19523
20197
|
};
|
|
19524
|
-
return { runInitial, maybeCompactInLoop };
|
|
20198
|
+
return { getLastCompactionOutcome: () => lastCompactionOutcome, runInitial, maybeCompactInLoop: () => prepareRequest(), forceCompact, prepareRequest };
|
|
19525
20199
|
}
|
|
19526
20200
|
|
|
19527
20201
|
// packages/agent-runtime/providerCallTelemetry.ts
|
|
19528
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
|
+
}
|
|
19529
20248
|
var shortHash = (value) => createHash4("sha1").update(value).digest("hex").slice(0, 12);
|
|
19530
20249
|
var hashMessage = (message) => {
|
|
19531
20250
|
let text2;
|
|
@@ -19565,6 +20284,7 @@ function createDivergeTracker(max4 = DIVERGE_TRACKER_MAX_DIALOGS) {
|
|
|
19565
20284
|
var processDivergeTracker = createDivergeTracker();
|
|
19566
20285
|
function buildRequestTelemetry(args2) {
|
|
19567
20286
|
try {
|
|
20287
|
+
const provenance = projectContextProvenance(args2.provenance);
|
|
19568
20288
|
const hashes = args2.messages.map(hashMessage);
|
|
19569
20289
|
let toolResultChars = 0;
|
|
19570
20290
|
let toolResultCount = 0;
|
|
@@ -19580,6 +20300,7 @@ function buildRequestTelemetry(args2) {
|
|
|
19580
20300
|
const diverge = (args2.tracker ?? processDivergeTracker).observe(args2.dialogKey, hashes);
|
|
19581
20301
|
return {
|
|
19582
20302
|
...args2.toolsHash ? { toolsHash: args2.toolsHash } : {},
|
|
20303
|
+
...provenance ? { provenance } : {},
|
|
19583
20304
|
msgCount: args2.messages.length,
|
|
19584
20305
|
contentChars,
|
|
19585
20306
|
toolResultChars,
|
|
@@ -19599,13 +20320,23 @@ function hashToolDefinitions(tools) {
|
|
|
19599
20320
|
}
|
|
19600
20321
|
|
|
19601
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
|
+
};
|
|
19602
20333
|
var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
|
|
19603
20334
|
var LLM_REQUEST_TIMEOUT = "LLM_REQUEST_TIMEOUT";
|
|
19604
20335
|
var DEFAULT_LLM_REQUEST_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
19605
20336
|
var DEFAULT_COMPACTION_TIMEOUT_MS = 60 * 1e3;
|
|
19606
20337
|
var DEFAULT_ROUND_BUDGET_WARNING_THRESHOLD = 25;
|
|
19607
20338
|
function buildRoundBudgetWarningPrompt(threshold) {
|
|
19608
|
-
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`;
|
|
19609
20340
|
}
|
|
19610
20341
|
var ROUND_BUDGET_WARNING_PROMPT = buildRoundBudgetWarningPrompt(
|
|
19611
20342
|
DEFAULT_ROUND_BUDGET_WARNING_THRESHOLD
|
|
@@ -19635,23 +20366,24 @@ var CONCURRENT_READONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
|
19635
20366
|
]);
|
|
19636
20367
|
function partitionToolCallsIntoBatches(toolCalls) {
|
|
19637
20368
|
const batches = [];
|
|
19638
|
-
let
|
|
19639
|
-
|
|
19640
|
-
|
|
19641
|
-
|
|
19642
|
-
|
|
19643
|
-
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
|
|
19649
|
-
|
|
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;
|
|
19650
20383
|
}
|
|
20384
|
+
currentBatch.push({ index, toolCall });
|
|
19651
20385
|
}
|
|
19652
|
-
|
|
19653
|
-
batches.push({ isConcurrent: true, calls: currentReadBatch });
|
|
19654
|
-
}
|
|
20386
|
+
flush2();
|
|
19655
20387
|
return batches;
|
|
19656
20388
|
}
|
|
19657
20389
|
function resolveLlmRequestTimeoutMs(input) {
|
|
@@ -19660,7 +20392,7 @@ function resolveLlmRequestTimeoutMs(input) {
|
|
|
19660
20392
|
}
|
|
19661
20393
|
function resolveCompactionTimeoutMs(input) {
|
|
19662
20394
|
const raw = input.compactionTimeoutMs;
|
|
19663
|
-
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;
|
|
19664
20396
|
}
|
|
19665
20397
|
function readHostCompactionSummaryFallback(adapter) {
|
|
19666
20398
|
const value = adapter.compactionSummaryFallback;
|
|
@@ -19785,6 +20517,10 @@ function attachUsageRecordsToError(error, usageRecords) {
|
|
|
19785
20517
|
}
|
|
19786
20518
|
async function persistFailedLocalTurn(args2) {
|
|
19787
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
|
+
});
|
|
19788
20524
|
try {
|
|
19789
20525
|
const saved = await args2.adapter.saveTurn({
|
|
19790
20526
|
agentKey: args2.agentKey,
|
|
@@ -19795,6 +20531,7 @@ async function persistFailedLocalTurn(args2) {
|
|
|
19795
20531
|
toolCallCount: args2.toolCallCount ?? 0,
|
|
19796
20532
|
error: true,
|
|
19797
20533
|
errorMessage,
|
|
20534
|
+
...businessCompletion ? { businessCompletion } : {},
|
|
19798
20535
|
...args2.usage ? { usage: args2.usage } : {}
|
|
19799
20536
|
},
|
|
19800
20537
|
...args2.accountingUsage ? { accountingUsage: args2.accountingUsage } : {},
|
|
@@ -19828,6 +20565,18 @@ async function loadAdapterDialogHistory(adapter, dialogId, options) {
|
|
|
19828
20565
|
}
|
|
19829
20566
|
return { messages: await adapter.loadDialogHistory(dialogId) };
|
|
19830
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
|
+
}
|
|
19831
20580
|
async function runLocalAgentTurn(input) {
|
|
19832
20581
|
const legacyCallbacks = {
|
|
19833
20582
|
onLoopEvent: input.onLoopEvent,
|
|
@@ -19841,17 +20590,6 @@ async function runLocalAgentTurn(input) {
|
|
|
19841
20590
|
observationBoundary.attachCallbacks(legacyCallbacks);
|
|
19842
20591
|
}
|
|
19843
20592
|
const loopTiming = createLoopTiming();
|
|
19844
|
-
const subtaskBudgetClock = input.subtaskBudgetNow ?? (() => Date.now());
|
|
19845
|
-
const subtaskBudgetLimits = {
|
|
19846
|
-
maxToolCalls: input.subtaskMaxToolCalls ?? input.subtaskBudgetLimits?.maxToolCalls ?? DEFAULT_SUBTASK_MAX_TOOL_CALLS,
|
|
19847
|
-
maxWallClockMs: input.subtaskMaxWallClockMs ?? input.subtaskBudgetLimits?.maxWallClockMs ?? DEFAULT_SUBTASK_MAX_WALL_CLOCK_MS
|
|
19848
|
-
};
|
|
19849
|
-
const subtaskBudgetTracker = input.runKind === "subtask" ? createSubtaskBudgetTracker({
|
|
19850
|
-
limits: subtaskBudgetLimits,
|
|
19851
|
-
now: subtaskBudgetClock,
|
|
19852
|
-
// 墙钟从 run 开始计(含 provider 初始化与首轮前的准备)。
|
|
19853
|
-
startedAtMs: subtaskBudgetClock()
|
|
19854
|
-
}) : null;
|
|
19855
20593
|
try {
|
|
19856
20594
|
loopTiming.mark("turnStart", 0);
|
|
19857
20595
|
let agentConfig = await input.adapter.loadAgentConfig(input.agentRef);
|
|
@@ -19939,7 +20677,8 @@ async function runLocalAgentTurn(input) {
|
|
|
19939
20677
|
if (input.strictContinueHistory && (loaded.source === "none" || loaded.source === "partial")) {
|
|
19940
20678
|
throw new Error(`Strict continuation history unavailable: ${loaded.source}`);
|
|
19941
20679
|
}
|
|
19942
|
-
|
|
20680
|
+
const currentIds = new Set(input.userMessages?.map((message) => message.cliMessageId));
|
|
20681
|
+
history = loaded.messages.filter((message) => !currentIds.has(message.cliMessageId));
|
|
19943
20682
|
dialogHistorySource = loaded.source;
|
|
19944
20683
|
}
|
|
19945
20684
|
} catch (error) {
|
|
@@ -20025,6 +20764,9 @@ async function runLocalAgentTurn(input) {
|
|
|
20025
20764
|
// 平台风控纪律:无条件系统层块,沿用 session 占位约定。
|
|
20026
20765
|
{ content: PLATFORM_RISK_CONTROL_RULE, cacheScope: "session" },
|
|
20027
20766
|
{ content: buildConsultationModeBlock(), cacheScope: "session" },
|
|
20767
|
+
// Git 任务隔离:系统层固定前置,四条装配线同序(请教模式之后、身份信息之前;
|
|
20768
|
+
// skill 配置 disabled 也注入)。
|
|
20769
|
+
{ content: WORKTREE_ISOLATION_PRELUDE, cacheScope: "session" },
|
|
20028
20770
|
{ content: identityBlock, cacheScope: "session" },
|
|
20029
20771
|
...guidanceScopes,
|
|
20030
20772
|
// 回复行为准则:local 线(CLI 非交互 / 桌面 / TUI)的唯一注入边界。
|
|
@@ -20041,13 +20783,33 @@ async function runLocalAgentTurn(input) {
|
|
|
20041
20783
|
}
|
|
20042
20784
|
return resolvedProvider;
|
|
20043
20785
|
};
|
|
20786
|
+
let resolvedSummaryProvider;
|
|
20787
|
+
const resolveSummaryProviderOnce = async () => {
|
|
20788
|
+
if (!resolvedSummaryProvider) {
|
|
20789
|
+
const provider = await input.adapter.resolveProvider(agentConfig, {
|
|
20790
|
+
textOnly: true,
|
|
20791
|
+
toolNames: [],
|
|
20792
|
+
prompt: ""
|
|
20793
|
+
});
|
|
20794
|
+
if (provider.textOnly !== true) {
|
|
20795
|
+
throw new Error("auto-compaction requires an isolated text-only provider");
|
|
20796
|
+
}
|
|
20797
|
+
resolvedSummaryProvider = provider;
|
|
20798
|
+
}
|
|
20799
|
+
return resolvedSummaryProvider;
|
|
20800
|
+
};
|
|
20044
20801
|
const contextWindow = resolveAgentContextWindow(agentConfig);
|
|
20045
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" });
|
|
20046
20806
|
const compaction = createTurnCompactionController({
|
|
20047
20807
|
adapter: input.adapter,
|
|
20048
20808
|
continueDialogId: input.continueDialogId,
|
|
20049
20809
|
model: agentConfig.model,
|
|
20050
|
-
|
|
20810
|
+
provider: agentConfig.provider,
|
|
20811
|
+
providerEndpoint: agentConfig.customProviderUrl,
|
|
20812
|
+
resolveProvider: resolveSummaryProviderOnce,
|
|
20051
20813
|
contextWindow,
|
|
20052
20814
|
compressionTriggerRatio,
|
|
20053
20815
|
abortSignal: input.abortSignal,
|
|
@@ -20067,19 +20829,18 @@ async function runLocalAgentTurn(input) {
|
|
|
20067
20829
|
)
|
|
20068
20830
|
],
|
|
20069
20831
|
getWorkingPrefix: () => transcript.working().slice(0, prefixCount),
|
|
20070
|
-
|
|
20832
|
+
onSelectedSummary: (summary) => {
|
|
20833
|
+
selectedSummary = summary;
|
|
20834
|
+
},
|
|
20835
|
+
replaceWorkingView: (next) => {
|
|
20836
|
+
transcript.replaceWorkingHistory(next);
|
|
20837
|
+
summaryProjectedPhase = contextPhase("summary-projected", next);
|
|
20838
|
+
},
|
|
20071
20839
|
contextReferenceResolver: input.adapter.host === "cli" ? input.contextReferenceResolver : void 0,
|
|
20072
20840
|
onUsage: (usage) => usageLedger.addCompaction(usage)
|
|
20073
20841
|
});
|
|
20074
|
-
|
|
20075
|
-
|
|
20076
|
-
const initialCompactionUsage = initialCompaction.usage;
|
|
20077
|
-
loopTiming.mark("maybeAutoCompactLocalHistory", 0);
|
|
20078
|
-
const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model, contextWindow);
|
|
20079
|
-
if (trimmedHistory.droppedCount > 0) {
|
|
20080
|
-
history = trimmedHistory.history;
|
|
20081
|
-
}
|
|
20082
|
-
loopTiming.mark("trimHistoryToContextBudget", 0);
|
|
20842
|
+
throwIfAborted(input);
|
|
20843
|
+
let budgetTrimPhase = contextPhase("budget-trim", history, { droppedCount: 0 });
|
|
20083
20844
|
const builtMessages = buildMessages({
|
|
20084
20845
|
prompt: agentConfig.prompt,
|
|
20085
20846
|
contextBlockScopes: mergedContextBlockScopes,
|
|
@@ -20111,6 +20872,14 @@ async function runLocalAgentTurn(input) {
|
|
|
20111
20872
|
...msg,
|
|
20112
20873
|
content: truncateToolOutputForContext(msg.content, contextWindow)
|
|
20113
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
|
+
}
|
|
20114
20883
|
const acceptToolImages = createToolImageLedger();
|
|
20115
20884
|
const transcript = createTurnTranscript({
|
|
20116
20885
|
initialWorking: messages,
|
|
@@ -20120,7 +20889,9 @@ async function runLocalAgentTurn(input) {
|
|
|
20120
20889
|
});
|
|
20121
20890
|
const userInputText = extractUserInputText(input.input);
|
|
20122
20891
|
let toolCallCount = 0;
|
|
20892
|
+
let requestCalibrationRatio = 1;
|
|
20123
20893
|
let result4 = { content: "" };
|
|
20894
|
+
let stopReason;
|
|
20124
20895
|
const usageLedger = createTurnUsageLedger({
|
|
20125
20896
|
model: agentConfig.model,
|
|
20126
20897
|
provider: agentConfig.provider,
|
|
@@ -20129,59 +20900,78 @@ async function runLocalAgentTurn(input) {
|
|
|
20129
20900
|
stablePrefixEstimatedTokens: builtMessages.stablePrefixEstimatedTokens
|
|
20130
20901
|
} : {}
|
|
20131
20902
|
});
|
|
20132
|
-
if (initialCompactionUsage) usageLedger.addCompaction(initialCompactionUsage);
|
|
20133
20903
|
let loopError;
|
|
20904
|
+
let consumedInjectedMessages = false;
|
|
20134
20905
|
let round = 0;
|
|
20135
|
-
let budgetExhaustion = null;
|
|
20136
|
-
const executedToolNameLog = [];
|
|
20137
|
-
const markBudgetExhausted = () => {
|
|
20138
|
-
if (!subtaskBudgetTracker || budgetExhaustion) return;
|
|
20139
|
-
const exhaustion = subtaskBudgetTracker.exhaustion();
|
|
20140
|
-
if (!exhaustion) return;
|
|
20141
|
-
budgetExhaustion = exhaustion;
|
|
20142
|
-
emitLoopEvent(observationBoundary, {
|
|
20143
|
-
kind: "budget-exhausted",
|
|
20144
|
-
limit: exhaustion.limit,
|
|
20145
|
-
atMs: exhaustion.atMs,
|
|
20146
|
-
maxToolCalls: exhaustion.limits.maxToolCalls,
|
|
20147
|
-
maxWallClockMs: exhaustion.limits.maxWallClockMs,
|
|
20148
|
-
toolCallsExecuted: exhaustion.toolCallsExecuted,
|
|
20149
|
-
elapsedMs: exhaustion.elapsedMs,
|
|
20150
|
-
round
|
|
20151
|
-
});
|
|
20152
|
-
};
|
|
20153
20906
|
let emptyAssistantRepairPending = false;
|
|
20154
20907
|
let emptyAssistantRepairUsed = false;
|
|
20155
20908
|
let reasoningEmptyRepairCount = 0;
|
|
20156
20909
|
let skipFinalAppend = false;
|
|
20157
20910
|
let partialContent = "";
|
|
20158
20911
|
const progressGuard = createLocalLoopProgressGuard(input.progressGuardConfig);
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
markBudgetExhausted();
|
|
20163
|
-
return false;
|
|
20912
|
+
let pendingInjectionCommits = [];
|
|
20913
|
+
let inFlightTransactions = [];
|
|
20914
|
+
let rollbackInjectionCommits = async () => {
|
|
20164
20915
|
};
|
|
20165
20916
|
try {
|
|
20166
20917
|
const provider = await resolveProviderOnce();
|
|
20167
|
-
const applyPendingInjections = () => {
|
|
20918
|
+
const applyPendingInjections = async () => {
|
|
20168
20919
|
if (!input.drainInjections) return false;
|
|
20169
|
-
|
|
20170
|
-
try {
|
|
20171
|
-
pending = input.drainInjections() ?? [];
|
|
20172
|
-
} catch (error) {
|
|
20173
|
-
console.warn("[localLoop] drainInjections failed:", error);
|
|
20174
|
-
return false;
|
|
20175
|
-
}
|
|
20920
|
+
const pending = await input.drainInjections() ?? [];
|
|
20176
20921
|
let injected = false;
|
|
20177
|
-
for (const
|
|
20178
|
-
if (typeof
|
|
20179
|
-
|
|
20180
|
-
|
|
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;
|
|
20181
20947
|
injected = true;
|
|
20182
20948
|
}
|
|
20183
20949
|
return injected;
|
|
20184
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
|
+
};
|
|
20185
20975
|
const newDialogTelemetryKey = `new:${crypto.randomUUID()}`;
|
|
20186
20976
|
let roundBudgetWarningInjected = false;
|
|
20187
20977
|
const roundWarningThreshold = input.roundBudgetWarningThreshold ?? DEFAULT_ROUND_BUDGET_WARNING_THRESHOLD;
|
|
@@ -20189,12 +20979,47 @@ async function runLocalAgentTurn(input) {
|
|
|
20189
20979
|
partialContent = "";
|
|
20190
20980
|
throwIfAborted(input);
|
|
20191
20981
|
loopTiming.mark("roundStart", round);
|
|
20192
|
-
applyPendingInjections();
|
|
20982
|
+
await applyPendingInjections();
|
|
20193
20983
|
if (roundWarningThreshold > 0 && round >= roundWarningThreshold && !roundBudgetWarningInjected) {
|
|
20194
20984
|
const prompt = buildRoundBudgetWarningPrompt(roundWarningThreshold);
|
|
20195
20985
|
transcript.push({ role: "user", content: prompt });
|
|
20196
20986
|
roundBudgetWarningInjected = true;
|
|
20197
20987
|
}
|
|
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);
|
|
20198
21023
|
const preparedMessages = prepareMessagesForProviderCall(transcript.working());
|
|
20199
21024
|
if (!supportsImages && hasImageInRuntimeMessages(preparedMessages.messages) && !imageDowngradeEmitted) {
|
|
20200
21025
|
emitLoopEvent(observationBoundary, {
|
|
@@ -20204,11 +21029,27 @@ async function runLocalAgentTurn(input) {
|
|
|
20204
21029
|
});
|
|
20205
21030
|
imageDowngradeEmitted = true;
|
|
20206
21031
|
}
|
|
20207
|
-
const
|
|
20208
|
-
|
|
20209
|
-
|
|
20210
|
-
|
|
20211
|
-
|
|
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 });
|
|
20212
21053
|
const contextMetrics = {
|
|
20213
21054
|
...preparedMessages.metrics,
|
|
20214
21055
|
messageCount: requestMessages.length,
|
|
@@ -20236,63 +21077,109 @@ async function runLocalAgentTurn(input) {
|
|
|
20236
21077
|
// 无 dialogId 的新对话用本 turn 唯一键,避免不同新对话共用一个槽误报漂移。
|
|
20237
21078
|
dialogKey: input.continueDialogId || newDialogTelemetryKey,
|
|
20238
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
|
+
},
|
|
20239
21086
|
toolsHash: safeToolNamesHash(agentTools)
|
|
20240
21087
|
});
|
|
20241
|
-
if (!budgetAdmissionGate()) {
|
|
20242
|
-
break;
|
|
20243
|
-
}
|
|
20244
21088
|
resetToolImageDelivery(requestMessages.flatMap(toolImages));
|
|
20245
|
-
|
|
20246
|
-
|
|
20247
|
-
|
|
20248
|
-
|
|
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
|
+
},
|
|
20249
21153
|
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
20250
|
-
|
|
20251
|
-
|
|
20252
|
-
|
|
20253
|
-
|
|
20254
|
-
|
|
20255
|
-
|
|
20256
|
-
|
|
20257
|
-
|
|
20258
|
-
|
|
20259
|
-
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20263
|
-
|
|
20264
|
-
|
|
20265
|
-
|
|
20266
|
-
}
|
|
20267
|
-
|
|
20268
|
-
|
|
20269
|
-
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
|
|
20275
|
-
}
|
|
20276
|
-
|
|
20277
|
-
|
|
20278
|
-
|
|
20279
|
-
kind: "tool-event",
|
|
20280
|
-
event,
|
|
20281
|
-
round,
|
|
20282
|
-
atMs: Date.now()
|
|
20283
|
-
});
|
|
20284
|
-
} } : {},
|
|
20285
|
-
...shouldPassToolEvents ? { toolEventRound: round } : {}
|
|
20286
|
-
},
|
|
20287
|
-
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
20288
|
-
activityVersion: () => llmStreamActivity,
|
|
20289
|
-
round,
|
|
20290
|
-
input,
|
|
20291
|
-
boundary: observationBoundary,
|
|
20292
|
-
context: contextMetrics,
|
|
20293
|
-
providerName: agentConfig.provider,
|
|
20294
|
-
model: provider.model
|
|
20295
|
-
});
|
|
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
|
+
}
|
|
20296
21183
|
acceptToolImages.discard(requestMessages.flatMap(toolImages).filter((image) => toolImageDelivery(image) === "impossible"));
|
|
20297
21184
|
acceptToolImages.commit(
|
|
20298
21185
|
requestMessages.flatMap(toolImages).filter((image) => toolImageDelivery(image) === "delivered"),
|
|
@@ -20302,13 +21189,25 @@ async function runLocalAgentTurn(input) {
|
|
|
20302
21189
|
const pending = toolImages(message).filter((image) => supportsImages && !toolImageDelivery(image));
|
|
20303
21190
|
return pending.length ? { ...message, [TOOL_IMAGES]: pending } : stripToolImages(message);
|
|
20304
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);
|
|
20305
21198
|
loopTiming.mark("llmCall", round);
|
|
20306
21199
|
usageLedger.recordProviderCall({
|
|
20307
21200
|
usage: result4.usage,
|
|
20308
21201
|
model: result4.model,
|
|
20309
21202
|
provider: result4.provider,
|
|
20310
|
-
telemetry: finalizeCallTelemetry(requestTelemetry, result4, round, callStartedAt)
|
|
21203
|
+
telemetry: { ...finalizeCallTelemetry(requestTelemetry, result4, round, callStartedAt), requestState: "completed" }
|
|
20311
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
|
+
}
|
|
20312
21211
|
const assistantGuardVerdict = progressGuard.observeAssistantResponse(result4);
|
|
20313
21212
|
if (assistantGuardVerdict.action === "stall") {
|
|
20314
21213
|
emitLoopEvent(observationBoundary, {
|
|
@@ -20326,11 +21225,11 @@ async function runLocalAgentTurn(input) {
|
|
|
20326
21225
|
};
|
|
20327
21226
|
break;
|
|
20328
21227
|
}
|
|
20329
|
-
if (result4.runtimeProviderFailure) {
|
|
21228
|
+
if (result4.error || result4.runtimeProviderFailure) {
|
|
20330
21229
|
result4 = {
|
|
20331
21230
|
...result4,
|
|
20332
21231
|
error: true,
|
|
20333
|
-
errorMessage: result4.runtimeProviderFailure.
|
|
21232
|
+
errorMessage: result4.runtimeProviderFailure?.message ?? result4.errorMessage
|
|
20334
21233
|
};
|
|
20335
21234
|
break;
|
|
20336
21235
|
}
|
|
@@ -20393,13 +21292,14 @@ ${reasoningTailLog}
|
|
|
20393
21292
|
...result4.reasoning_content ? { reasoning_content: result4.reasoning_content } : {}
|
|
20394
21293
|
};
|
|
20395
21294
|
transcript.push(assistantMessage);
|
|
20396
|
-
if (applyPendingInjections()) {
|
|
21295
|
+
if (await applyPendingInjections()) {
|
|
20397
21296
|
loopTiming.mark("roundEnd", round);
|
|
20398
21297
|
round += 1;
|
|
20399
21298
|
continue;
|
|
20400
21299
|
}
|
|
20401
21300
|
transcript.popLast();
|
|
20402
21301
|
}
|
|
21302
|
+
stopReason = "done";
|
|
20403
21303
|
break;
|
|
20404
21304
|
}
|
|
20405
21305
|
const outputBlocks = result4.output ?? [];
|
|
@@ -20418,9 +21318,11 @@ ${reasoningTailLog}
|
|
|
20418
21318
|
}
|
|
20419
21319
|
}
|
|
20420
21320
|
if (hasInlineExecutedTools) {
|
|
20421
|
-
for (const blockMsg of blocksToOpenAiMessages(outputBlocks)) {
|
|
21321
|
+
for (const blockMsg of blocksToOpenAiMessages(outputBlocks, input.adapter.workspaceRoot)) {
|
|
20422
21322
|
transcript.pushTool(blockMsg);
|
|
20423
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";
|
|
20424
21326
|
skipFinalAppend = true;
|
|
20425
21327
|
break;
|
|
20426
21328
|
}
|
|
@@ -20437,15 +21339,10 @@ ${reasoningTailLog}
|
|
|
20437
21339
|
const executedToolResults = [];
|
|
20438
21340
|
loopTiming.mark("toolLoopStart", round);
|
|
20439
21341
|
const slotResults = new Array(toolCalls.length);
|
|
20440
|
-
const runSingleTool = async ({ index, toolCall }) => {
|
|
20441
|
-
throwIfAborted(
|
|
20442
|
-
if (!budgetAdmissionGate()) {
|
|
20443
|
-
skippedToolCalls.push(toolCall);
|
|
20444
|
-
return;
|
|
20445
|
-
}
|
|
20446
|
-
subtaskBudgetTracker?.recordToolCallExecuted();
|
|
21342
|
+
const runSingleTool = async ({ index, toolCall }, executionInput = input, isClosed = () => false) => {
|
|
21343
|
+
throwIfAborted(executionInput);
|
|
20447
21344
|
const { toolResult, toolExecMs } = await executeToolCall({
|
|
20448
|
-
input,
|
|
21345
|
+
input: executionInput,
|
|
20449
21346
|
toolCall,
|
|
20450
21347
|
round,
|
|
20451
21348
|
boundary: observationBoundary,
|
|
@@ -20458,12 +21355,12 @@ ${reasoningTailLog}
|
|
|
20458
21355
|
...result4.finish_reason ? { finishReason: result4.finish_reason } : {}
|
|
20459
21356
|
}
|
|
20460
21357
|
});
|
|
21358
|
+
if (isClosed()) return;
|
|
20461
21359
|
slotResults[index] = {
|
|
20462
21360
|
toolName: toolCall.function.name,
|
|
20463
21361
|
toolResult,
|
|
20464
21362
|
toolExecMs
|
|
20465
21363
|
};
|
|
20466
|
-
executedToolNameLog.push(toolCall.function.name);
|
|
20467
21364
|
};
|
|
20468
21365
|
const commitSlot = (i) => {
|
|
20469
21366
|
const toolCall = toolCalls[i];
|
|
@@ -20482,7 +21379,8 @@ ${reasoningTailLog}
|
|
|
20482
21379
|
content: formatToolMessageContent({
|
|
20483
21380
|
toolName,
|
|
20484
21381
|
content: toolResult.content,
|
|
20485
|
-
metadata: observedMetadata
|
|
21382
|
+
metadata: observedMetadata,
|
|
21383
|
+
workspaceRoot: input.adapter.workspaceRoot
|
|
20486
21384
|
}),
|
|
20487
21385
|
tool_call_id: toolCall.id,
|
|
20488
21386
|
toolName,
|
|
@@ -20494,14 +21392,36 @@ ${reasoningTailLog}
|
|
|
20494
21392
|
} } : {}
|
|
20495
21393
|
});
|
|
20496
21394
|
};
|
|
20497
|
-
const skippedToolCalls = [];
|
|
20498
21395
|
const batches = partitionToolCallsIntoBatches(toolCalls);
|
|
20499
21396
|
for (const batch of batches) {
|
|
20500
21397
|
throwIfAborted(input);
|
|
20501
21398
|
let batchError;
|
|
20502
21399
|
try {
|
|
20503
21400
|
if (batch.isConcurrent && batch.calls.length > 1) {
|
|
20504
|
-
|
|
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;
|
|
20505
21425
|
} else {
|
|
20506
21426
|
for (const call of batch.calls) {
|
|
20507
21427
|
await runSingleTool(call);
|
|
@@ -20518,15 +21438,20 @@ ${reasoningTailLog}
|
|
|
20518
21438
|
}
|
|
20519
21439
|
if (batchError) throw batchError;
|
|
20520
21440
|
}
|
|
20521
|
-
|
|
20522
|
-
|
|
20523
|
-
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
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;
|
|
20528
21452
|
}
|
|
20529
|
-
if (
|
|
21453
|
+
if (executedToolResults.some(({ metadata }) => metadata?.uiAskChoice === true && metadata.resolved !== true)) {
|
|
21454
|
+
stopReason = "pending";
|
|
20530
21455
|
break;
|
|
20531
21456
|
}
|
|
20532
21457
|
const toolExecutionGuardVerdict = progressGuard.observeToolExecution(
|
|
@@ -20549,31 +21474,28 @@ ${reasoningTailLog}
|
|
|
20549
21474
|
};
|
|
20550
21475
|
break;
|
|
20551
21476
|
}
|
|
20552
|
-
await compaction.maybeCompactInLoop();
|
|
20553
|
-
if (!budgetAdmissionGate()) {
|
|
20554
|
-
break;
|
|
20555
|
-
}
|
|
20556
21477
|
loopTiming.mark("roundEnd", round);
|
|
20557
21478
|
round += 1;
|
|
20558
21479
|
}
|
|
20559
21480
|
} catch (error) {
|
|
20560
|
-
|
|
20561
|
-
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
exhaustion: budgetExhaustion,
|
|
20570
|
-
roundsCompleted: round,
|
|
20571
|
-
recentToolNames: executedToolNameLog
|
|
20572
|
-
})
|
|
20573
|
-
].filter((part) => part.length > 0).join("\n\n")
|
|
20574
|
-
};
|
|
21481
|
+
const toRollback = [...pendingInjectionCommits.splice(0), ...inFlightTransactions];
|
|
21482
|
+
inFlightTransactions = [];
|
|
21483
|
+
let rollbackErr;
|
|
21484
|
+
try {
|
|
21485
|
+
await rollbackInjectionCommits(toRollback);
|
|
21486
|
+
} catch (rbErr) {
|
|
21487
|
+
rollbackErr = rbErr;
|
|
21488
|
+
}
|
|
21489
|
+
loopError = rollbackErr ? combineRollbackError(error, rollbackErr) : error;
|
|
20575
21490
|
}
|
|
21491
|
+
if (!loopError && input.abortSignal?.aborted) loopError = buildAbortedError();
|
|
20576
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
|
+
}
|
|
20577
21499
|
const turnMessages2 = transcript.persisted(
|
|
20578
21500
|
sanitizedPersistedInput,
|
|
20579
21501
|
input.persistedInputReference
|
|
@@ -20599,6 +21521,16 @@ ${reasoningTailLog}
|
|
|
20599
21521
|
throw loopError;
|
|
20600
21522
|
}
|
|
20601
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;
|
|
20602
21534
|
if (!skipFinalAppend) {
|
|
20603
21535
|
const truncatedReasoningTailLog = resolveTruncatedReasoningTailLog(
|
|
20604
21536
|
result4.emptyAssistantFallbackReason,
|
|
@@ -20685,6 +21617,231 @@ function buildResponsesRequestBody(body, model, options) {
|
|
|
20685
21617
|
};
|
|
20686
21618
|
}
|
|
20687
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
|
+
|
|
20688
21845
|
// packages/agent-runtime/responsesSseStream.ts
|
|
20689
21846
|
function toResponsesStreamFailure(raw, fallbackPrefix = "Responses") {
|
|
20690
21847
|
if (!raw || typeof raw !== "object") return void 0;
|
|
@@ -20721,6 +21878,8 @@ function hasNumericTokenCount(u) {
|
|
|
20721
21878
|
function createResponsesStreamCollector(callbacks) {
|
|
20722
21879
|
let content = "";
|
|
20723
21880
|
let reasoning = "";
|
|
21881
|
+
const textSanitizer = createResponsesProtocolLeakSanitizer(callbacks?.onTextDelta);
|
|
21882
|
+
let sawNonEmptyOutputTextDelta = false;
|
|
20724
21883
|
const toolCallsAcc = createResponsesToolAccumulator();
|
|
20725
21884
|
let usage;
|
|
20726
21885
|
let failure;
|
|
@@ -20772,8 +21931,8 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
20772
21931
|
return;
|
|
20773
21932
|
}
|
|
20774
21933
|
if (type === "response.output_text.delta" && typeof ev.delta === "string") {
|
|
20775
|
-
|
|
20776
|
-
|
|
21934
|
+
if (ev.delta.length > 0) sawNonEmptyOutputTextDelta = true;
|
|
21935
|
+
textSanitizer.push(ev.delta);
|
|
20777
21936
|
return;
|
|
20778
21937
|
}
|
|
20779
21938
|
if ((type === "response.reasoning_text.delta" || type === "response.reasoning.delta") && typeof ev.delta === "string") {
|
|
@@ -20783,11 +21942,11 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
20783
21942
|
}
|
|
20784
21943
|
if (type === "response.output_item.added" || type === "response.output_item.done") {
|
|
20785
21944
|
const item = ev.item;
|
|
20786
|
-
if (item?.type === "message" && !
|
|
21945
|
+
if (item?.type === "message" && !sawNonEmptyOutputTextDelta) {
|
|
20787
21946
|
const itemText = extractOutputTextFromItem(item);
|
|
20788
21947
|
if (itemText) {
|
|
20789
|
-
|
|
20790
|
-
|
|
21948
|
+
sawNonEmptyOutputTextDelta = true;
|
|
21949
|
+
textSanitizer.push(itemText);
|
|
20791
21950
|
}
|
|
20792
21951
|
}
|
|
20793
21952
|
applyResponsesToolEvent(toolCallsAcc, ev);
|
|
@@ -20886,8 +22045,16 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
20886
22045
|
if (authoritativeCompletedTools && failure) {
|
|
20887
22046
|
finalToolCalls = [];
|
|
20888
22047
|
}
|
|
22048
|
+
const sanitized = textSanitizer.finalize();
|
|
22049
|
+
content = sanitized.content;
|
|
22050
|
+
let intercepted = sanitized.intercepted;
|
|
20889
22051
|
if (!content && completedResponse) {
|
|
20890
|
-
|
|
22052
|
+
const extracted = extractTextFromResponseOutput(completedResponse);
|
|
22053
|
+
if (extracted) {
|
|
22054
|
+
const sanitizedExtracted = sanitizeResponsesProtocolLeakText(extracted);
|
|
22055
|
+
content = sanitizedExtracted.content;
|
|
22056
|
+
if (sanitizedExtracted.intercepted) intercepted = true;
|
|
22057
|
+
}
|
|
20891
22058
|
}
|
|
20892
22059
|
if (!reasoning && completedResponse) {
|
|
20893
22060
|
reasoning = extractReasoningFromResponseOutput(completedResponse);
|
|
@@ -20902,6 +22069,7 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
20902
22069
|
...streamComplete ? { finish_reason: finalToolCalls.length > 0 ? "tool_calls" : "stop" } : {},
|
|
20903
22070
|
...streamComplete ? { stream_complete: true } : {},
|
|
20904
22071
|
...streamTruncated ? { stream_truncated: true } : {},
|
|
22072
|
+
...intercepted ? { leaked_protocol_intercepted: true } : {},
|
|
20905
22073
|
...completedResponse ? { completed_response: completedResponse } : {},
|
|
20906
22074
|
...completedResponse && typeof completedResponse.id === "string" ? { response_id: completedResponse.id } : {},
|
|
20907
22075
|
...failure ? { failure } : {}
|
|
@@ -21210,7 +22378,7 @@ async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
|
21210
22378
|
terminalIfEnabled(isAbortError(error) ? "aborted" : "network-error");
|
|
21211
22379
|
throw error;
|
|
21212
22380
|
}
|
|
21213
|
-
if (res.status === 401 && args2.resolveApiKey) {
|
|
22381
|
+
if (res.status === 401 && args2.resolveApiKey && !args2.noRetries) {
|
|
21214
22382
|
const refreshed = await args2.resolveApiKey({ force: true });
|
|
21215
22383
|
if (refreshed && refreshed !== apiKey) {
|
|
21216
22384
|
diagnosticCall?.httpResult(diagnosticAttempt, {
|
|
@@ -21283,6 +22451,7 @@ async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
|
21283
22451
|
...streamed2.usage ? { usage: streamed2.usage } : {},
|
|
21284
22452
|
...streamed2.stream_complete ? { stream_complete: true } : {},
|
|
21285
22453
|
...streamed2.finish_reason ? { finish_reason: streamed2.finish_reason } : {},
|
|
22454
|
+
...streamed2.leaked_protocol_intercepted ? { leaked_protocol_intercepted: true } : {},
|
|
21286
22455
|
trace: args2.messages
|
|
21287
22456
|
});
|
|
21288
22457
|
}
|
|
@@ -21330,6 +22499,16 @@ async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
|
21330
22499
|
throw error;
|
|
21331
22500
|
}
|
|
21332
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
|
+
}
|
|
21333
22512
|
|
|
21334
22513
|
// packages/agent-runtime/openAiCompatibleProviderConfig.ts
|
|
21335
22514
|
async function resolveOpenAiCompatibleProviderConfig(args2) {
|
|
@@ -22435,9 +23614,23 @@ async function fetchHybridRemoteRecord(args2) {
|
|
|
22435
23614
|
...args2.signal ? { signal: args2.signal } : {}
|
|
22436
23615
|
}
|
|
22437
23616
|
);
|
|
22438
|
-
if (!response.ok)
|
|
22439
|
-
|
|
22440
|
-
|
|
23617
|
+
if (!response.ok) {
|
|
23618
|
+
if (response.status !== 404) args2.onUnavailable?.();
|
|
23619
|
+
return null;
|
|
23620
|
+
}
|
|
23621
|
+
let payload;
|
|
23622
|
+
try {
|
|
23623
|
+
payload = await response.json();
|
|
23624
|
+
} catch {
|
|
23625
|
+
args2.onUnavailable?.();
|
|
23626
|
+
return null;
|
|
23627
|
+
}
|
|
23628
|
+
const record2 = payload && typeof payload === "object" && "data" in payload ? payload.data : payload;
|
|
23629
|
+
if (record2 !== null && (!record2 || typeof record2 !== "object" || Array.isArray(record2))) {
|
|
23630
|
+
args2.onUnavailable?.();
|
|
23631
|
+
return null;
|
|
23632
|
+
}
|
|
23633
|
+
return normalizeHybridRecord(args2.dbKey, record2, args2.server);
|
|
22441
23634
|
}
|
|
22442
23635
|
function shouldCacheHybridRemoteRecord(remoteRecord, localRecord) {
|
|
22443
23636
|
if (!remoteRecord || typeof remoteRecord !== "object") return false;
|
|
@@ -22459,14 +23652,18 @@ function createHybridRecordStore(deps) {
|
|
|
22459
23652
|
const normalizedLocalRecord = normalizeHybridRecord(dbKey, localRecord);
|
|
22460
23653
|
if (normalizedLocalRecord && options?.remote !== true) return normalizedLocalRecord;
|
|
22461
23654
|
if (options?.remote === false) return null;
|
|
22462
|
-
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;
|
|
22463
23657
|
for (const server of resolveHybridServers(
|
|
22464
23658
|
deps.defaultServer,
|
|
22465
23659
|
options?.preferredServerOrigin,
|
|
22466
23660
|
deps.fallbackServers
|
|
22467
23661
|
)) {
|
|
22468
23662
|
const remainingMs = fallbackDeadlineMs === null ? null : fallbackDeadlineMs - Date.now();
|
|
22469
|
-
if (remainingMs !== null && remainingMs <= 0)
|
|
23663
|
+
if (remainingMs !== null && remainingMs <= 0) {
|
|
23664
|
+
options?.onRemoteUnavailable?.();
|
|
23665
|
+
break;
|
|
23666
|
+
}
|
|
22470
23667
|
let remoteRecord = null;
|
|
22471
23668
|
try {
|
|
22472
23669
|
remoteRecord = await fetchHybridRemoteRecord({
|
|
@@ -22474,9 +23671,11 @@ function createHybridRecordStore(deps) {
|
|
|
22474
23671
|
server,
|
|
22475
23672
|
authToken: deps.authToken,
|
|
22476
23673
|
fetchImpl,
|
|
23674
|
+
onUnavailable: options?.onRemoteUnavailable,
|
|
22477
23675
|
...remainingMs !== null ? { signal: AbortSignal.timeout(remainingMs) } : {}
|
|
22478
23676
|
});
|
|
22479
23677
|
} catch {
|
|
23678
|
+
options?.onRemoteUnavailable?.();
|
|
22480
23679
|
continue;
|
|
22481
23680
|
}
|
|
22482
23681
|
if (!remoteRecord) continue;
|
|
@@ -22505,6 +23704,267 @@ function createHybridRecordStore(deps) {
|
|
|
22505
23704
|
var DEFAULT_SANDBOX_TMPFS_SIZE_BYTES = 128 * 1024 * 1024;
|
|
22506
23705
|
var BWRAP_PROBE_TTL_MS = 5 * 6e4;
|
|
22507
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
|
+
|
|
22508
23968
|
// packages/cli/client/localDialogRecords.ts
|
|
22509
23969
|
var localDialogMessageRecordToRuntimeMessage = dialogMessageRecordToAgentRuntimeMessage;
|
|
22510
23970
|
function buildLocalDialogWritePlan(args2) {
|
|
@@ -22521,6 +23981,138 @@ function buildLocalDialogWritePlan(args2) {
|
|
|
22521
23981
|
...args2.titleOverride ? { titleOverride: args2.titleOverride } : {}
|
|
22522
23982
|
});
|
|
22523
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
|
+
}
|
|
22524
24116
|
|
|
22525
24117
|
// packages/agent-runtime/noloWorkspaceTools.node.ts
|
|
22526
24118
|
async function readNoloProcessStream(readable) {
|
|
@@ -22636,7 +24228,7 @@ function buildLoadSkillExecutor(args2) {
|
|
|
22636
24228
|
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
22637
24229
|
const referenceKeys = ["source", "slug", "projectBinding", "relativePath", "dbKey", "id", "skillId"];
|
|
22638
24230
|
if (referenceKeys.some((key) => Object.hasOwn(parsed, key))) {
|
|
22639
|
-
return loadPreciseSkill(args2.cwd, parsed);
|
|
24231
|
+
return loadPreciseSkill(args2.cwd, parsed, args2.agentSkillSource, args2.resolveAgentSkillSource);
|
|
22640
24232
|
}
|
|
22641
24233
|
const name = noloStringArg(parsed.name ?? parsed.skillName ?? parsed.skill);
|
|
22642
24234
|
if (!name) {
|
|
@@ -22645,12 +24237,14 @@ function buildLoadSkillExecutor(args2) {
|
|
|
22645
24237
|
metadata: { loadSkill: true, resolved: false }
|
|
22646
24238
|
};
|
|
22647
24239
|
}
|
|
22648
|
-
const { resolveSkillByName } = await import("./skillDiscovery-
|
|
24240
|
+
const { resolveSkillByName } = await import("./skillDiscovery-B5V23AXP.js");
|
|
22649
24241
|
const resolved = resolveSkillByName(args2.cwd, name);
|
|
22650
24242
|
if (!resolved) {
|
|
22651
|
-
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-
|
|
24243
|
+
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-2ECA42FC.js");
|
|
22652
24244
|
const builtin = resolveBuiltinSkillByName(name);
|
|
22653
24245
|
if (builtin) {
|
|
24246
|
+
const denied = await rejectDisabledBuiltin(args2.agentSkillSource, builtin.slug, name, args2.resolveAgentSkillSource);
|
|
24247
|
+
if (denied) return denied;
|
|
22654
24248
|
return {
|
|
22655
24249
|
content: `Skill "${name}" loaded inline. Follow its instructions.
|
|
22656
24250
|
|
|
@@ -22690,7 +24284,25 @@ ${body}`,
|
|
|
22690
24284
|
}
|
|
22691
24285
|
};
|
|
22692
24286
|
}
|
|
22693
|
-
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) {
|
|
22694
24306
|
const source = parsed.source;
|
|
22695
24307
|
const has2 = (key) => Object.hasOwn(parsed, key);
|
|
22696
24308
|
const reject = (reason) => ({
|
|
@@ -22707,9 +24319,11 @@ async function loadPreciseSkill(cwd, parsed) {
|
|
|
22707
24319
|
if (!nonEmpty(parsed.slug) || has2("projectBinding") || has2("relativePath")) {
|
|
22708
24320
|
return reject("builtin requires only an exact slug.");
|
|
22709
24321
|
}
|
|
22710
|
-
const { listBuiltinSkills } = await import("./builtinSkillRegistry-
|
|
24322
|
+
const { listBuiltinSkills } = await import("./builtinSkillRegistry-2ECA42FC.js");
|
|
22711
24323
|
const builtin = listBuiltinSkills().find((entry) => entry.slug === parsed.slug);
|
|
22712
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 } };
|
|
22713
24327
|
return {
|
|
22714
24328
|
content: `Skill "${builtin.slug}" loaded inline. Follow its instructions.
|
|
22715
24329
|
|
|
@@ -22731,7 +24345,7 @@ ${builtin.content}`,
|
|
|
22731
24345
|
}
|
|
22732
24346
|
try {
|
|
22733
24347
|
const { realpathSync, statSync, readFileSync } = await import("node:fs");
|
|
22734
|
-
const { resolve: resolve6, relative: relative6, isAbsolute: isAbsolute5, basename:
|
|
24348
|
+
const { resolve: resolve6, relative: relative6, isAbsolute: isAbsolute5, basename: basename4, sep: sep3 } = await import("node:path");
|
|
22735
24349
|
const inside = (root, target) => {
|
|
22736
24350
|
const rel = relative6(root, target);
|
|
22737
24351
|
return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep3}`) && !isAbsolute5(rel);
|
|
@@ -22740,7 +24354,7 @@ ${builtin.content}`,
|
|
|
22740
24354
|
if (!isAbsolute5(parsed.projectBinding) || realpathSync(parsed.projectBinding) !== realCwd) {
|
|
22741
24355
|
return reject("projectBinding does not match the authorized cwd.");
|
|
22742
24356
|
}
|
|
22743
|
-
if (isAbsolute5(parsed.relativePath) ||
|
|
24357
|
+
if (isAbsolute5(parsed.relativePath) || basename4(parsed.relativePath) !== "SKILL.md") {
|
|
22744
24358
|
return reject("relativePath must reference a project SKILL.md.");
|
|
22745
24359
|
}
|
|
22746
24360
|
const skillsRoot = resolve6(realCwd, ".agents", "skills");
|
|
@@ -22748,7 +24362,7 @@ ${builtin.content}`,
|
|
|
22748
24362
|
if (!inside(skillsRoot, candidate)) return reject("path is outside cwd/.agents/skills/.");
|
|
22749
24363
|
const realRoot = realpathSync(skillsRoot);
|
|
22750
24364
|
const realPath = realpathSync(candidate);
|
|
22751
|
-
if (realRoot !== skillsRoot || !inside(realRoot, realPath) ||
|
|
24365
|
+
if (realRoot !== skillsRoot || !inside(realRoot, realPath) || basename4(realPath) !== "SKILL.md") {
|
|
22752
24366
|
return reject("skill path escapes cwd/.agents/skills/ or is not SKILL.md.");
|
|
22753
24367
|
}
|
|
22754
24368
|
if (!statSync(realPath).isFile()) return reject("SKILL.md is not a file.");
|
|
@@ -22771,7 +24385,7 @@ ${body}`,
|
|
|
22771
24385
|
}
|
|
22772
24386
|
}
|
|
22773
24387
|
async function formatUnknownSkillMessage(cwd, requestedName) {
|
|
22774
|
-
const { discoverSkills } = await import("./skillDiscovery-
|
|
24388
|
+
const { discoverSkills } = await import("./skillDiscovery-B5V23AXP.js");
|
|
22775
24389
|
let available = [];
|
|
22776
24390
|
try {
|
|
22777
24391
|
available = discoverSkills(cwd).map((s) => s.name);
|
|
@@ -23423,6 +25037,7 @@ export {
|
|
|
23423
25037
|
evaluateShellCommandPolicy,
|
|
23424
25038
|
filterRetainedLedgerRecords,
|
|
23425
25039
|
isLineRangeCovered,
|
|
25040
|
+
runTaskStop,
|
|
23426
25041
|
WORKSPACE_TOOL_NAMES,
|
|
23427
25042
|
buildLocalWorkspaceToolset,
|
|
23428
25043
|
buildLocalWorkspacePolicyToolNames,
|
|
@@ -23435,12 +25050,16 @@ export {
|
|
|
23435
25050
|
createLocalWorkspaceToolExecutors,
|
|
23436
25051
|
buildToolParametersIndex,
|
|
23437
25052
|
getAgentRuntimeToolParametersIndex,
|
|
25053
|
+
registerLocalShellLifecycle,
|
|
25054
|
+
getLocalShellLifecycle,
|
|
23438
25055
|
normalizeLocalToolName,
|
|
23439
25056
|
isCommandExecutingTool,
|
|
23440
25057
|
resolveLocalToolPolicy,
|
|
23441
25058
|
runExecShellGates,
|
|
23442
25059
|
executeLocalToolWithPolicy,
|
|
23443
25060
|
LOCAL_TURN_ABORTED_CODE,
|
|
25061
|
+
evaluateTaskExecutionContract,
|
|
25062
|
+
projectContextProvenance,
|
|
23444
25063
|
hashToolDefinitions,
|
|
23445
25064
|
LOCAL_AGENT_CONFIG_MISSING_CODE,
|
|
23446
25065
|
runLocalAgentTurn,
|
|
@@ -23452,6 +25071,7 @@ export {
|
|
|
23452
25071
|
parseOpenAiCompatibleChatCompletionResponse,
|
|
23453
25072
|
readOpenAiCompatibleSseCompletion,
|
|
23454
25073
|
executeOpenAiCompatibleChatCompletion,
|
|
25074
|
+
describeOpenAiCompatibleRequestBudget,
|
|
23455
25075
|
resolveOpenAiCompatibleProviderConfig,
|
|
23456
25076
|
dialogMessageRecordToAgentRuntimeMessage,
|
|
23457
25077
|
buildAgentRuntimeDialogWritePlan,
|
|
@@ -23459,8 +25079,15 @@ export {
|
|
|
23459
25079
|
parseSyncServersEnv,
|
|
23460
25080
|
DEFAULT_HYBRID_READ_TIMEOUT_MS,
|
|
23461
25081
|
createHybridRecordStore,
|
|
25082
|
+
registerDialogOwner,
|
|
23462
25083
|
localDialogMessageRecordToRuntimeMessage,
|
|
23463
25084
|
buildLocalDialogWritePlan,
|
|
25085
|
+
saveCliPendingUserMessages,
|
|
25086
|
+
readCliPendingUserMessages,
|
|
25087
|
+
markCliUserBatchPhase,
|
|
25088
|
+
rollbackCliUserBatchPhase,
|
|
25089
|
+
buildCliBatchCompletionOp,
|
|
25090
|
+
resolveCliUnknownBatchWithoutResend,
|
|
23464
25091
|
buildNoloWorkspaceCliToolExecutors,
|
|
23465
25092
|
buildLoadSkillExecutor,
|
|
23466
25093
|
isStableSessionIdentityEnabled,
|