nolo-cli 0.105.0-alpha.2 → 0.105.0
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 +1 -1
- package/{_executeModel-4W7C3ACS.js → _executeModel-JXG5TLPE.js} +75 -68
- package/action-GVA5ARSJ.js +20 -0
- package/{addContentAction-O7R66HEX.js → addContentAction-J3DLDV64.js} +12 -11
- package/{addDialogAgentAction-74OA7KYP.js → addDialogAgentAction-PHIXJCF2.js} +18 -19
- package/{agentDeleteCommand-YB3S2LPY.js → agentDeleteCommand-2AWJGHXG.js} +117 -42
- package/{agentEmailCommands-J6YBHL42.js → agentEmailCommands-VV5OSILE.js} +98 -88
- package/agentListCommands-OQMRBDWP.js +742 -0
- package/{agentMachineCommands-2RWGEBA3.js → agentMachineCommands-3VLLR6RL.js} +48 -43
- package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-XPJYZSCE.js} +97 -2
- package/{agentPullCommand-O5MPVJ5E.js → agentPullCommand-B4T2DJ5H.js} +1 -1
- package/agentRecordCommands-GPIARVOW.js +138 -0
- package/agentRunCommand-LRJTZ7IM.js +167 -0
- package/{agentRunControl-AVJR4JW4.js → agentRunControl-3HWA2LLQ.js} +2 -2
- package/{agentRuntimeLocal-FRUE5P2V.js → agentRuntimeLocal-PV6AZOEU.js} +44 -39
- package/{agentSlice-6LBOYNKN.js → agentSlice-6R3JKS6I.js} +14 -13
- package/{appDeleteCommands-JPWTSFID.js → appDeleteCommands-WEX73P5R.js} +46 -41
- package/{appDeployCommands-YCVY2UYO.js → appDeployCommands-7BAXWA4M.js} +46 -41
- package/{appDeployStatusCommands-JMCEIKTI.js → appDeployStatusCommands-EJ6A2U4X.js} +46 -41
- package/{appGetCommands-EXWT3QAE.js → appGetCommands-SB355OEX.js} +46 -41
- package/{appListCommands-PKRLSWRE.js → appListCommands-TSZDPIKJ.js} +46 -41
- package/{authCommand-F4EFRRX6.js → authCommand-5PB3YRVV.js} +118 -24
- package/{authCommands-RGOGCPP6.js → authCommands-5RTUDYZW.js} +7 -5
- package/{builtinSkillRegistry-FUAVTRVZ.js → builtinSkillRegistry-SBBWTANC.js} +10 -8
- package/{chromeCommands-FZYAU75D.js → chromeCommands-AU5ZJXBG.js} +289 -37
- package/{chromeOpsCommands-62P2Q2YB.js → chromeOpsCommands-ZYTCMNHG.js} +156 -22
- package/{chunk-6OZ36FXI.js → chunk-27ONFIEY.js} +22 -4
- package/{chunk-JEDZAO7L.js → chunk-2SYTUTLI.js} +257 -37
- package/{chunk-HVURBGF3.js → chunk-2U3NHADM.js} +6 -6
- package/{chunk-53HEEOTT.js → chunk-2WJ57RJA.js} +83 -16
- package/{chunk-OIVSQH2O.js → chunk-3BXNTXYI.js} +299 -5
- package/{chunk-V4MJDUSR.js → chunk-3F424ASC.js} +2 -2
- package/{chunk-HJUYAD4A.js → chunk-3Q7NEHAR.js} +5 -5
- package/chunk-44CU7CKA.js +13545 -0
- package/{chunk-EYAQT56M.js → chunk-4DPP773Q.js} +2 -2
- package/chunk-4LCOCOR5.js +50 -0
- package/{chunk-JPGCXHNM.js → chunk-4LKMZ3RR.js} +1 -1
- package/{chunk-2GRGFCF6.js → chunk-4VJAC32I.js} +2 -1
- package/{chunk-6D6VBVEW.js → chunk-4W24JM32.js} +80 -14
- package/{chunk-H62HCIUP.js → chunk-4WMMIL66.js} +35 -22
- package/{chunk-MC4XLIJ7.js → chunk-523DITKR.js} +1 -1
- package/{chunk-ZCYXJSTU.js → chunk-54VPQTOA.js} +66 -94
- package/{chunk-E4MARS3Q.js → chunk-5GVBDNTO.js} +1 -1
- package/chunk-5MMAK75Q.js +15 -0
- package/{chunk-7S4YWN7P.js → chunk-5UUIGN6I.js} +4 -4
- package/{chunk-42V6BK2E.js → chunk-62IL3KQV.js} +4 -34
- package/{chunk-GQBOR3G6.js → chunk-7KVZ5LDQ.js} +2 -2
- package/chunk-A4SQRTZ6.js +15 -0
- package/{chunk-L5UXH3B2.js → chunk-AFH5QC6R.js} +58 -9
- package/{chunk-AEOE4Z6Q.js → chunk-AFSY3ZMB.js} +39 -15
- package/chunk-AGIM7IMJ.js +147 -0
- package/{chunk-5UTFL4QJ.js → chunk-AOTBKDRK.js} +7 -0
- package/{chunk-NA35QHCF.js → chunk-AWVP7PPG.js} +1 -1
- package/{chunk-EEGDMATE.js → chunk-B7APRSPS.js} +86 -81
- package/{chunk-W324THOB.js → chunk-BB7LVBTS.js} +20 -11
- package/{chunk-6YTOJY35.js → chunk-BZ7NPA6G.js} +35 -2
- package/{chunk-5H7KJX7J.js → chunk-CFHWVEUJ.js} +5 -5
- package/chunk-CHOZJMJS.js +78 -0
- package/{chunk-ETI2NYVF.js → chunk-CNA27EMD.js} +4 -4
- package/{chunk-ACTMNVHM.js → chunk-CYSYR67N.js} +1 -1
- package/{chunk-WV42OMV7.js → chunk-D2GQE6AF.js} +8 -8
- package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
- package/{chunk-Q554LLSI.js → chunk-DMXLXZKL.js} +1 -1
- package/chunk-DZ7R5V3Y.js +164 -0
- package/{chunk-3VNWWVKB.js → chunk-E3YWHWCR.js} +50 -18
- package/{chunk-KQ4ONNQD.js → chunk-EKPKW6RM.js} +155 -8
- package/{chunk-2J5Y72GY.js → chunk-EP7BWZ4B.js} +1 -1
- package/{chunk-ABQYVJBJ.js → chunk-EV235ILT.js} +5 -5
- package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
- package/{chunk-3ZW5ZJMM.js → chunk-FGSJ3YMD.js} +23 -28
- package/{chunk-2F7RJC6L.js → chunk-FOXQ7BAB.js} +1 -1
- package/{chunk-SH43IESU.js → chunk-GGC55Q32.js} +199 -29
- package/chunk-GMZLP5DV.js +82 -0
- package/{chunk-DHDMC6FO.js → chunk-GSKPJIHY.js} +14 -9
- package/{chunk-FDTR4QJ6.js → chunk-H6A6X4EK.js} +32 -1
- package/{chunk-DVINR3PL.js → chunk-HDLLCBRF.js} +1 -1
- package/{chunk-QOKAKDPE.js → chunk-HIM3FCLF.js} +0 -1
- package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
- package/{chunk-VLTIYV3X.js → chunk-HP57OUJO.js} +4 -4
- package/{chunk-NXUYQBDZ.js → chunk-HYXABXCZ.js} +29 -78
- package/{chunk-DNCEALKX.js → chunk-IEJ5YDA4.js} +22 -29
- package/{chunk-O6OSWFZQ.js → chunk-IHPDK6UD.js} +6 -0
- package/{chunk-BP4XNZRM.js → chunk-JIXGJTBU.js} +4 -4
- package/{chunk-GPCZ7UXG.js → chunk-K6U4NKFJ.js} +1 -1
- package/{chunk-Z77CRGTW.js → chunk-KA5O5KQL.js} +1 -1
- package/{chunk-4OEFYTWL.js → chunk-L5WOICCV.js} +67 -48
- package/{chunk-LS2ZANRJ.js → chunk-LOCNXNOU.js} +1 -1
- package/chunk-LWLNLZC5.js +265 -0
- package/{chunk-H66KLASO.js → chunk-LWXE6IFU.js} +567 -519
- package/{chunk-PUOC4YRO.js → chunk-M7VLQGQP.js} +11 -0
- package/chunk-NKWIS6G2.js +442 -0
- package/{chunk-BFU6C242.js → chunk-NMFV26UG.js} +1 -1
- package/{chunk-DJWMIXDZ.js → chunk-NSAFG343.js} +10 -10
- package/{chunk-UKZDAFYT.js → chunk-NSBID7PR.js} +6 -10
- package/{chunk-U7ISRJQO.js → chunk-NTR4SD3P.js} +845 -240
- package/{chunk-FZGV4FGK.js → chunk-NUHHBEJC.js} +378 -187
- package/chunk-NWENLDMM.js +42 -0
- package/chunk-O7SVKKLY.js +875 -0
- package/chunk-OCZKATRC.js +129 -0
- package/{chunk-VMFTFOWF.js → chunk-OKGVNZTL.js} +35 -8
- package/{chunk-KQHGZWSV.js → chunk-OXME3PEE.js} +1 -1
- package/{chunk-JRQFUXY7.js → chunk-P5GCTVGV.js} +99 -22
- package/{chunk-PQFHGD77.js → chunk-QKTESDWK.js} +161 -14
- package/{chunk-U3JZVWIB.js → chunk-QMXJ5KDJ.js} +68 -46
- package/{chunk-GEPUP7OO.js → chunk-QYUBY3OZ.js} +3 -3
- package/{chunk-3BMYXEUW.js → chunk-R5AJODNI.js} +1 -1
- package/{chunk-J4MOO56S.js → chunk-RILRSUGC.js} +10 -2
- package/{chunk-OEVAY4J6.js → chunk-RWX7AY7J.js} +18 -20
- package/{chunk-YY7I6GQ3.js → chunk-S2NSK7AZ.js} +11 -9
- package/{chunk-IIVGDG4I.js → chunk-SJKULPGX.js} +13 -7
- package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
- package/chunk-TY3TIUJK.js +89 -0
- package/{chunk-I3TQJXQ7.js → chunk-U3C3IA32.js} +9 -2
- package/{chunk-UZGQNTVW.js → chunk-UA324D4O.js} +8 -6
- package/{chunk-YYLHWIW6.js → chunk-UKZX3NHN.js} +1 -1
- package/chunk-UWXDA7L5.js +8005 -0
- package/{chunk-3DII57IT.js → chunk-VCAQFMVN.js} +1 -1
- package/chunk-VIWDGTDA.js +8 -0
- package/chunk-VJVNU77E.js +83 -0
- package/{chunk-A6FMKU7M.js → chunk-VVJ2ENLY.js} +47 -67
- package/{chunk-UKWGR5SS.js → chunk-VY6VFGKR.js} +194 -1144
- package/{chunk-QDSINZM3.js → chunk-WJ3B6FX6.js} +1 -14
- package/{chunk-Q67DOFOO.js → chunk-Y3PMXGLH.js} +2 -0
- package/chunk-YK5MHOWM.js +915 -0
- package/chunk-YV25TM3R.js +780 -0
- package/{chunk-TOP2VXOR.js → chunk-YVU4XVJD.js} +5 -5
- package/{chunk-HVP6P5FV.js → chunk-Z5NGE5DH.js} +29 -9
- package/{chunk-LC43IGO4.js → chunk-ZBHR642M.js} +704 -950
- package/chunk-ZRAU6T47.js +56 -0
- package/{chunk-XPVRVN4U.js → chunk-ZSUDOTPL.js} +19 -17
- package/commandRegistry-QU62WJQX.js +833 -0
- package/{contentThunks-LXOZUD2Y.js → contentThunks-VGV3JJVB.js} +37 -35
- package/{cooldownCommands-REAWYVTY.js → cooldownCommands-ZLEPIB4A.js} +2 -2
- package/{createAgentAutomationAction-M5NDEIC6.js → createAgentAutomationAction-ZNVLI4WV.js} +39 -37
- package/createDialogAction-TTUA46DT.js +69 -0
- package/{createPageAction-WY5ZKP2M.js → createPageAction-KUFSC5XW.js} +46 -43
- package/{chunk-OWS6OYF4.js → cursorProvider-YGGNMVWX.js} +2751 -10172
- package/{dbSlice-XVWBAGYN.js → dbSlice-MYEETO73.js} +11 -10
- package/{deleteFile-YG6QMJLU.js → deleteFile-KESP65GC.js} +7 -6
- package/{dialogCommands-YVMHDEOX.js → dialogCommands-DRDPEOTL.js} +49 -45
- package/{dialogSlice-HSGREZGA.js → dialogSlice-V2SVSTIV.js} +41 -34
- package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
- package/{docCreateCommands-7UTWDYJU.js → docCreateCommands-M26CFDDQ.js} +48 -43
- package/{docDeleteCommands-GG6BJ4PS.js → docDeleteCommands-LRZHCKVX.js} +49 -44
- package/{docReadCommands-QHMQVSLP.js → docReadCommands-6QJSISHK.js} +47 -42
- package/{docStore-IIS36NGG.js → docStore-4RWAFNDM.js} +16 -12
- package/{docUpdateCommands-QPL6IVUK.js → docUpdateCommands-W4KU4U5T.js} +48 -43
- package/{fetchMessages-EIU7UFFK.js → fetchMessages-3PXAHKCR.js} +5 -5
- package/{getPricing-LUSEABA6.js → getPricing-NMMFT3YI.js} +4 -4
- package/{handleSendMessageAction-FEHCWMN2.js → handleSendMessageAction-VEWLGB5Z.js} +107 -41
- package/index.js +87 -884
- package/{lib-FRRS27KN.js → lib-PU2G2MSO.js} +523 -191
- package/{localDialogRead-BTFJ4V2I.js → localDialogRead-UYCKO7YZ.js} +2 -2
- package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-TU6OBC76.js} +9 -6
- package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-VKWVOPPI.js} +1 -1
- package/{machineCommands-ERCXIPJC.js → machineCommands-AEHHCJEW.js} +92 -82
- package/machineWsRunDispatch-MY2KHS36.js +154 -0
- package/{memberThunks-QGFLFVCI.js → memberThunks-EE6TI3TV.js} +20 -18
- package/{models-T3SG6MJ5.js → models-ZPU5EDF4.js} +2 -2
- package/oauthTokenStore-ITEB663N.js +23 -0
- package/package.json +1 -1
- package/pdf-U6KSUEZZ.js +26435 -0
- package/processSpawn-SOAV3FEV.js +11 -0
- package/profileConfig-ZGOFORWV.js +43 -0
- package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-TEBH7FDX.js} +7 -7
- package/{providerRegistry-757OWH3O.js → providerRegistry-CBJLNCET.js} +11 -7
- package/{read-COE3ZYR6.js → read-PJIT2YEJ.js} +7 -6
- package/{readDocTool-5USN4A6V.js → readDocTool-DRSXHGNL.js} +5 -3
- package/{readlineWorkspace-PXATJOED.js → readlineWorkspace-7Q6MITLV.js} +2605 -2031
- package/{removeDialogAgentAction-IX3MN2ZO.js → removeDialogAgentAction-IN4WUKJJ.js} +21 -25
- package/{runAgentClientLoop-UY76PPZM.js → runAgentClientLoop-H2JALUVD.js} +76 -70
- package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-PIVSBZRZ.js} +4 -4
- package/runtimeModeArgs-2Y7BALTO.js +31 -0
- package/{setDialogExtraReferencesAction-X4HCPNZL.js → setDialogExtraReferencesAction-VDRF7LPK.js} +15 -13
- package/{setPrimaryDialogAgentAction-4GMIQLOD.js → setPrimaryDialogAgentAction-RO6LIWJ4.js} +22 -26
- package/{chunk-AFUORTY4.js → settingThunks-3OPOLOIA.js} +226 -940
- package/{skillDiscovery-CYUCJMAG.js → skillDiscovery-ZBU76COE.js} +3 -3
- package/{slateUtils-RIZES3PV.js → slateUtils-NGV2NMKM.js} +1 -1
- package/{spaceCommands-BMXKR7H6.js → spaceCommands-UBLL5EF2.js} +51 -46
- package/{streamAgentChatTurn-3YVIO4KE.js → streamAgentChatTurn-FFJWW3FD.js} +214 -108
- package/{switchDialogAgentAction-N52LRPA3.js → switchDialogAgentAction-MVF2JNE7.js} +18 -19
- package/{tableCommands-O6NWHFKV.js → tableCommands-6U4BMLRR.js} +10 -10
- package/{toolApiClient-QVJ6HDNN.js → toolApiClient-EJT6TMFG.js} +3 -3
- package/tools-AZRYLYNK.js +116 -0
- package/{tuiSummaryLlmCaller-WFRWERGK.js → tuiSummaryLlmCaller-7S5HJ3MT.js} +25 -22
- package/{updateCommands-2M74UL7P.js → updateCommands-4EHDLF5J.js} +3 -3
- package/{updateDialogTitleAction-GF5T3VMK.js → updateDialogTitleAction-5WXTRUJM.js} +82 -44
- package/action-YVYQEAAV.js +0 -31
- package/agentListCommands-3GWH4E4G.js +0 -410
- package/agentRecordCommands-UOF6YM5M.js +0 -128
- package/agentRunCommand-AVBWVTAJ.js +0 -156
- package/browser-image-compression-MFDTD7K6.js +0 -1763
- package/chatQueueReduxAdapter-WFROMKD3.js +0 -186
- package/chunk-CQ3WA2NE.js +0 -299
- package/chunk-FQUHIG5X.js +0 -20782
- package/chunk-M76ECQRD.js +0 -13658
- package/chunk-MEYIRKDN.js +0 -8967
- package/chunk-Q5FJJ6XI.js +0 -103
- package/chunk-S7Z2HMCN.js +0 -25
- package/chunk-Y5GCAMGP.js +0 -9
- package/chunk-YPREESF4.js +0 -225
- package/createDialogAction-TDFOINOY.js +0 -65
- package/machineWsRunDispatch-OVA3G76V.js +0 -144
- package/settingSlice-ZQZVUPKK.js +0 -204
- package/syncMapping-N6RGXGBW.js +0 -437
- package/tools-Q6IBBG33.js +0 -110
- package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
- package/{db-WK5MDZVN.js → db-VQSAOWAO.js} +1 -1
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEVIN_CONNECT_URL,
|
|
3
|
+
parseSseDataLineJson,
|
|
4
|
+
parseSseDataLineObject
|
|
5
|
+
} from "./chunk-YK5MHOWM.js";
|
|
1
6
|
import {
|
|
2
7
|
applyChatCompletionDelta,
|
|
3
8
|
applyResponsesToolEvent,
|
|
@@ -5,13 +10,15 @@ import {
|
|
|
5
10
|
finalizeResponsesToolCalls,
|
|
6
11
|
flushChatCompletionStream,
|
|
7
12
|
providerHttpFailure,
|
|
8
|
-
readSseFrames,
|
|
9
|
-
streamSseDataValues,
|
|
10
13
|
throwIfChatCompletionStreamFailed
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-54VPQTOA.js";
|
|
12
15
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
readSseFrames
|
|
17
|
+
} from "./chunk-GMZLP5DV.js";
|
|
18
|
+
import {
|
|
19
|
+
evaluateFileWritePolicy,
|
|
20
|
+
summarizeToolArguments
|
|
21
|
+
} from "./chunk-CHOZJMJS.js";
|
|
15
22
|
import {
|
|
16
23
|
clipToolText,
|
|
17
24
|
hasImageInRuntimeMessages,
|
|
@@ -20,13 +27,13 @@ import {
|
|
|
20
27
|
resolveHistoricalToolContentCap,
|
|
21
28
|
resolveToolOutputProfile,
|
|
22
29
|
stripImagePartsFromMessages
|
|
23
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-CFHWVEUJ.js";
|
|
24
31
|
import {
|
|
25
32
|
downgradeUnparsableToolCalls,
|
|
26
33
|
hasParsableObjectArguments,
|
|
27
34
|
repairTruncatedToolArguments,
|
|
28
35
|
sanitizeForOutbound
|
|
29
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-NKWIS6G2.js";
|
|
30
37
|
import {
|
|
31
38
|
createThinkParserState,
|
|
32
39
|
createToolCallAccumulator,
|
|
@@ -35,6 +42,7 @@ import {
|
|
|
35
42
|
finalizeAccumulatedToolCalls
|
|
36
43
|
} from "./chunk-N7J63Q6C.js";
|
|
37
44
|
import {
|
|
45
|
+
DELETE_SAFETY_RED_LINE,
|
|
38
46
|
TOOL_GUIDED_SECTION_ORDER,
|
|
39
47
|
buildIdentityBlock,
|
|
40
48
|
buildRuntimeGuidanceBlocks,
|
|
@@ -46,17 +54,18 @@ import {
|
|
|
46
54
|
requiresBareImageUrl,
|
|
47
55
|
resolveToolGuidedSections,
|
|
48
56
|
toBareImageUrlMessages
|
|
49
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-AFH5QC6R.js";
|
|
50
58
|
import {
|
|
51
59
|
convertMessagesToResponsesInput,
|
|
52
60
|
extractReasoningFromResponseOutput,
|
|
53
61
|
extractTextFromResponseOutput,
|
|
54
62
|
extractToolCallsFromResponseOutput,
|
|
55
63
|
getUsageRequestOptions,
|
|
64
|
+
shouldReplayReasoningContentForOutbound,
|
|
56
65
|
shouldStripReasoningContentForOutbound,
|
|
57
66
|
toOpenAiCompatibleMessages,
|
|
58
67
|
toResponsesTools
|
|
59
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-M7VLQGQP.js";
|
|
60
69
|
import {
|
|
61
70
|
BRIDGE_STREAM_MAX_CHARS,
|
|
62
71
|
DEFAULT_READ_DIALOG_MAX_RESPONSE_CHARS,
|
|
@@ -71,16 +80,7 @@ import {
|
|
|
71
80
|
parseNoloWorkspaceToolArguments,
|
|
72
81
|
readTextStreamUpToChars,
|
|
73
82
|
resolveNoloDialogInput
|
|
74
|
-
} from "./chunk-
|
|
75
|
-
import {
|
|
76
|
-
getAntigravityUserAgent,
|
|
77
|
-
readAntigravityProjectId,
|
|
78
|
-
resolveAntigravityCloudCodeBaseUrl
|
|
79
|
-
} from "./chunk-UZGQNTVW.js";
|
|
80
|
-
import {
|
|
81
|
-
buildProviderAuthHeaders,
|
|
82
|
-
buildProviderExecutionPlan
|
|
83
|
-
} from "./chunk-6OZ36FXI.js";
|
|
83
|
+
} from "./chunk-SJKULPGX.js";
|
|
84
84
|
import {
|
|
85
85
|
buildDialogFallbackTitleFromUserInput
|
|
86
86
|
} from "./chunk-2MBTWINN.js";
|
|
@@ -94,13 +94,12 @@ import {
|
|
|
94
94
|
resolveEmptyAssistantFallbackMessage,
|
|
95
95
|
resolveEmptyAssistantOutcome,
|
|
96
96
|
resolveTruncatedReasoningTailLog
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-L5WOICCV.js";
|
|
98
98
|
import {
|
|
99
99
|
COMPACTION_SUMMARY_SCHEMA_VERSION,
|
|
100
100
|
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|
|
101
101
|
buildCompactionMetricsFromPlan,
|
|
102
102
|
buildCompactionUserContent,
|
|
103
|
-
clipCompactText,
|
|
104
103
|
createProviderCallTimingTracker,
|
|
105
104
|
finalizeProviderCallTiming,
|
|
106
105
|
formatCompactionMetricsLog,
|
|
@@ -113,37 +112,36 @@ import {
|
|
|
113
112
|
resolveCompressionTriggerRatio,
|
|
114
113
|
truncateToolOutputForContext,
|
|
115
114
|
withProviderCallTimingFields
|
|
116
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-IEJ5YDA4.js";
|
|
116
|
+
import {
|
|
117
|
+
clipCompactText
|
|
118
|
+
} from "./chunk-5MMAK75Q.js";
|
|
119
|
+
import {
|
|
120
|
+
asRecordOrEmpty
|
|
121
|
+
} from "./chunk-KX6YBIHG.js";
|
|
117
122
|
import {
|
|
118
123
|
estimateTokenCount
|
|
119
124
|
} from "./chunk-PSCNXBYA.js";
|
|
120
125
|
import {
|
|
121
126
|
resolveNoloStateDir
|
|
122
|
-
} from "./chunk-
|
|
123
|
-
import {
|
|
124
|
-
toErrorMessage
|
|
125
|
-
} from "./chunk-HNMXYYJR.js";
|
|
127
|
+
} from "./chunk-HNGRBWYF.js";
|
|
126
128
|
import {
|
|
127
129
|
buildDialogSummaryLayer
|
|
128
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-HDLLCBRF.js";
|
|
129
131
|
import {
|
|
130
132
|
buildUserResponseLanguageContext
|
|
131
|
-
} from "./chunk-
|
|
133
|
+
} from "./chunk-4VJAC32I.js";
|
|
132
134
|
import {
|
|
133
135
|
canonicalizeToolName,
|
|
134
136
|
canonicalizeToolNames
|
|
135
|
-
} from "./chunk-
|
|
136
|
-
import {
|
|
137
|
-
asRecordOrEmpty
|
|
138
|
-
} from "./chunk-KX6YBIHG.js";
|
|
137
|
+
} from "./chunk-IHPDK6UD.js";
|
|
139
138
|
import {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
} from "./chunk-VMFTFOWF.js";
|
|
139
|
+
buildProviderAuthHeaders,
|
|
140
|
+
buildProviderExecutionPlan
|
|
141
|
+
} from "./chunk-27ONFIEY.js";
|
|
144
142
|
import {
|
|
145
|
-
|
|
146
|
-
} from "./chunk-
|
|
143
|
+
toErrorMessage
|
|
144
|
+
} from "./chunk-HNMXYYJR.js";
|
|
147
145
|
import {
|
|
148
146
|
asTrimmedLowercaseString
|
|
149
147
|
} from "./chunk-QSJ3HFEF.js";
|
|
@@ -151,11 +149,19 @@ import {
|
|
|
151
149
|
isRecord
|
|
152
150
|
} from "./chunk-KUG52IAP.js";
|
|
153
151
|
import {
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
asTrimmedNonEmptyStringArray,
|
|
153
|
+
dialogMessageKey,
|
|
154
|
+
dialogMessageRange
|
|
155
|
+
} from "./chunk-OKGVNZTL.js";
|
|
156
|
+
import {
|
|
157
|
+
asOptionalFiniteNumber
|
|
158
|
+
} from "./chunk-WWC7I6TA.js";
|
|
156
159
|
import {
|
|
157
160
|
asOptionalPositiveFiniteNumber
|
|
158
161
|
} from "./chunk-U6VC4MU4.js";
|
|
162
|
+
import {
|
|
163
|
+
asTrimmedString
|
|
164
|
+
} from "./chunk-3EUW3WEO.js";
|
|
159
165
|
import {
|
|
160
166
|
normalizeServerOrigin
|
|
161
167
|
} from "./chunk-CF7PE763.js";
|
|
@@ -11901,6 +11907,7 @@ var toQueue = /* @__PURE__ */ dual(2, (self, options) => toQueueArray(self.chann
|
|
|
11901
11907
|
var runIntoQueue = /* @__PURE__ */ dual(2, (self, queue) => runIntoQueueArray(self.channel, queue));
|
|
11902
11908
|
|
|
11903
11909
|
// packages/agent-runtime/abortableKernel.ts
|
|
11910
|
+
var IDLE_WATCHDOG_SLICES = 20;
|
|
11904
11911
|
function runAbortableWithTimeout(args2) {
|
|
11905
11912
|
const taskEffect = Effect_exports.callback(
|
|
11906
11913
|
(resume) => {
|
|
@@ -11936,12 +11943,26 @@ function runAbortableWithTimeout(args2) {
|
|
|
11936
11943
|
raced = Effect_exports.raceFirst(taskEffect, abortEffect);
|
|
11937
11944
|
}
|
|
11938
11945
|
if (typeof args2.timeoutMs === "number") {
|
|
11939
|
-
const
|
|
11946
|
+
const outer = raced;
|
|
11940
11947
|
const timeoutMs = args2.timeoutMs;
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11948
|
+
const activityVersion = args2.activityVersion;
|
|
11949
|
+
const idleWatchdog = Effect_exports.gen(function* () {
|
|
11950
|
+
const sliceCount = activityVersion ? IDLE_WATCHDOG_SLICES : 1;
|
|
11951
|
+
const baseSliceMs = Math.max(1, Math.floor(timeoutMs / sliceCount));
|
|
11952
|
+
let idleMs = 0;
|
|
11953
|
+
for (; ; ) {
|
|
11954
|
+
const versionAtSliceStart = activityVersion?.();
|
|
11955
|
+
const sliceMs = Math.max(1, Math.min(timeoutMs - idleMs, baseSliceMs));
|
|
11956
|
+
yield* Effect_exports.sleep(Duration_exports.millis(sliceMs));
|
|
11957
|
+
idleMs += sliceMs;
|
|
11958
|
+
if (activityVersion && activityVersion() !== versionAtSliceStart) {
|
|
11959
|
+
idleMs = 0;
|
|
11960
|
+
continue;
|
|
11961
|
+
}
|
|
11962
|
+
if (idleMs >= timeoutMs) return { kind: "timeout" };
|
|
11963
|
+
}
|
|
11944
11964
|
});
|
|
11965
|
+
raced = Effect_exports.raceFirst(outer, idleWatchdog);
|
|
11945
11966
|
}
|
|
11946
11967
|
return args2.runtime ? args2.runtime.runPromise(raced) : Effect_exports.runPromise(raced);
|
|
11947
11968
|
}
|
|
@@ -12040,26 +12061,6 @@ function createLocalLoopObservationBoundary(initialCallbacks) {
|
|
|
12040
12061
|
};
|
|
12041
12062
|
}
|
|
12042
12063
|
|
|
12043
|
-
// packages/agent-runtime/fileWritePolicy.ts
|
|
12044
|
-
function evaluateFileWritePolicy(args2) {
|
|
12045
|
-
if (args2.sessionApproved) return { permissionDecision: "allow" };
|
|
12046
|
-
return {
|
|
12047
|
-
permissionDecision: "ask",
|
|
12048
|
-
permissionRequest: {
|
|
12049
|
-
id: "permission-file-write-session",
|
|
12050
|
-
tool: args2.tool,
|
|
12051
|
-
action: "file_write",
|
|
12052
|
-
title: "\u786E\u8BA4\u5199\u5165\u6587\u4EF6",
|
|
12053
|
-
body: `\u672C\u4F1A\u8BDD\u9996\u6B21\u5199\u5165\u6587\u4EF6\uFF1A${args2.path}\u3002\u6279\u51C6\u540E\u672C\u4F1A\u8BDD\u540E\u7EED\u5199\u5165\u4E0D\u518D\u9010\u6B21\u786E\u8BA4\u3002`,
|
|
12054
|
-
command: args2.path,
|
|
12055
|
-
suggestedRule: {
|
|
12056
|
-
scope: "session",
|
|
12057
|
-
pattern: { capability: "file_write", target: "session" }
|
|
12058
|
-
}
|
|
12059
|
-
}
|
|
12060
|
-
};
|
|
12061
|
-
}
|
|
12062
|
-
|
|
12063
12064
|
// packages/agent-runtime/toolCallPairing.ts
|
|
12064
12065
|
function readToolCallId(message) {
|
|
12065
12066
|
if (typeof message.tool_call_id === "string" && message.tool_call_id) {
|
|
@@ -12161,50 +12162,6 @@ function sanitizeToolCallPairing(messages) {
|
|
|
12161
12162
|
return output;
|
|
12162
12163
|
}
|
|
12163
12164
|
|
|
12164
|
-
// packages/agent-runtime/parseToolArguments.ts
|
|
12165
|
-
function parseToolArgumentsJson(raw) {
|
|
12166
|
-
if (!raw?.trim()) return {};
|
|
12167
|
-
try {
|
|
12168
|
-
return asRecordOrEmpty(JSON.parse(raw));
|
|
12169
|
-
} catch {
|
|
12170
|
-
return {};
|
|
12171
|
-
}
|
|
12172
|
-
}
|
|
12173
|
-
|
|
12174
|
-
// packages/agent-runtime/summarizeToolArguments.ts
|
|
12175
|
-
function clip(value, max4 = 240) {
|
|
12176
|
-
return clipCompactText(value, max4);
|
|
12177
|
-
}
|
|
12178
|
-
function summarizeToolArguments(toolName, rawArgs) {
|
|
12179
|
-
const args2 = parseToolArgumentsJson(rawArgs);
|
|
12180
|
-
const pick = (...keys3) => {
|
|
12181
|
-
for (const key of keys3) {
|
|
12182
|
-
const value = asOptionalTrimmedString(args2[key]);
|
|
12183
|
-
if (value) return value;
|
|
12184
|
-
}
|
|
12185
|
-
return "";
|
|
12186
|
-
};
|
|
12187
|
-
const command = pick("command", "cmd", "runCommand", "executeCommand", "bash");
|
|
12188
|
-
if (command) return clip(command);
|
|
12189
|
-
const query = pick("query", "pattern", "search", "q");
|
|
12190
|
-
if (query) return clip(query);
|
|
12191
|
-
const filePath = pick("filePath", "file_path", "path", "filename", "file");
|
|
12192
|
-
if (filePath) return clip(filePath);
|
|
12193
|
-
const keys2 = Object.keys(args2);
|
|
12194
|
-
if (keys2.length === 0) return "";
|
|
12195
|
-
return clip(
|
|
12196
|
-
keys2.slice(0, 6).map((key) => {
|
|
12197
|
-
const value = args2[key];
|
|
12198
|
-
if (typeof value === "string") return `${key}=${clip(value, 80)}`;
|
|
12199
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
12200
|
-
return `${key}=${String(value)}`;
|
|
12201
|
-
}
|
|
12202
|
-
if (Array.isArray(value)) return `${key}[${value.length}]`;
|
|
12203
|
-
return `${key}=${value === null ? "null" : typeof value}`;
|
|
12204
|
-
}).join(" ")
|
|
12205
|
-
);
|
|
12206
|
-
}
|
|
12207
|
-
|
|
12208
12165
|
// packages/agent-runtime/progressGuard.ts
|
|
12209
12166
|
var DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS = 5;
|
|
12210
12167
|
var DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS = 8;
|
|
@@ -12560,7 +12517,7 @@ function formatToolOverflowMarker(args2) {
|
|
|
12560
12517
|
}
|
|
12561
12518
|
|
|
12562
12519
|
// packages/agent-runtime/localAutoCompaction.ts
|
|
12563
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
12520
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
12564
12521
|
function toPlanCompressionMessages(history) {
|
|
12565
12522
|
return history.map((message, index) => ({
|
|
12566
12523
|
id: `local-${index}`,
|
|
@@ -12628,6 +12585,13 @@ function isColdResume(history, nowMs) {
|
|
|
12628
12585
|
}
|
|
12629
12586
|
async function maybeAutoCompactLocalHistory(args2) {
|
|
12630
12587
|
const { adapter, dialogId, history } = args2;
|
|
12588
|
+
const emitPhase = (phase) => {
|
|
12589
|
+
try {
|
|
12590
|
+
args2.onPhase?.(phase);
|
|
12591
|
+
} catch {
|
|
12592
|
+
}
|
|
12593
|
+
};
|
|
12594
|
+
emitPhase({ kind: "validating-context" });
|
|
12631
12595
|
const unchanged = (decision) => ({
|
|
12632
12596
|
history,
|
|
12633
12597
|
compressed: false,
|
|
@@ -12723,8 +12687,46 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
12723
12687
|
if (!plan.shouldCompress) {
|
|
12724
12688
|
return projectExisting();
|
|
12725
12689
|
}
|
|
12690
|
+
emitPhase({ kind: "compaction-start" });
|
|
12691
|
+
const compactionAttemptId = randomUUID();
|
|
12692
|
+
let compactionT0 = Date.now();
|
|
12693
|
+
let compactionInputTokens;
|
|
12694
|
+
let compactionPrevSummaryTokens;
|
|
12695
|
+
let compactionInputSource;
|
|
12696
|
+
let compactionPrevSummarySource;
|
|
12697
|
+
let primaryElapsedMs;
|
|
12698
|
+
let saveElapsedMs;
|
|
12699
|
+
const logCompactionTiming = (outcome, fields) => {
|
|
12700
|
+
if (compactionInputTokens === void 0 && compactionInputSource !== void 0) {
|
|
12701
|
+
compactionInputTokens = estimateTokenCount(compactionInputSource);
|
|
12702
|
+
}
|
|
12703
|
+
if (compactionPrevSummaryTokens === void 0 && compactionPrevSummarySource !== void 0) {
|
|
12704
|
+
compactionPrevSummaryTokens = estimateTokenCount(compactionPrevSummarySource);
|
|
12705
|
+
}
|
|
12706
|
+
console.log(
|
|
12707
|
+
`[compaction-timing] ${JSON.stringify({
|
|
12708
|
+
attemptId: compactionAttemptId,
|
|
12709
|
+
model: fields.model ?? args2.model ?? null,
|
|
12710
|
+
inputTokens: compactionInputTokens ?? null,
|
|
12711
|
+
prevSummaryTokens: compactionPrevSummaryTokens ?? null,
|
|
12712
|
+
outputChars: fields.outputChars ?? null,
|
|
12713
|
+
elapsedMs: Date.now() - compactionT0,
|
|
12714
|
+
primaryElapsedMs: primaryElapsedMs ?? null,
|
|
12715
|
+
// main 无 fallback 通道,保留该字段以兼容日志 schema。
|
|
12716
|
+
fallbackElapsedMs: null,
|
|
12717
|
+
saveElapsedMs: saveElapsedMs ?? null,
|
|
12718
|
+
outcome
|
|
12719
|
+
})}`
|
|
12720
|
+
);
|
|
12721
|
+
};
|
|
12726
12722
|
try {
|
|
12723
|
+
if (args2.abortSignal?.aborted) {
|
|
12724
|
+
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
12725
|
+
}
|
|
12727
12726
|
const provider = await args2.resolveProvider();
|
|
12727
|
+
if (args2.abortSignal?.aborted) {
|
|
12728
|
+
throw Object.assign(new Error("auto-compaction aborted"), { compactionReason: "aborted" });
|
|
12729
|
+
}
|
|
12728
12730
|
const msgsToCompress = plan.msgsToCompress;
|
|
12729
12731
|
const messagesText = formatMessagesForSummaryWithTruncation(msgsToCompress);
|
|
12730
12732
|
const fileOpsText = formatFileOperationsFromMessages(
|
|
@@ -12736,24 +12738,71 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
12736
12738
|
messagesText,
|
|
12737
12739
|
fileOpsText
|
|
12738
12740
|
});
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12741
|
+
emitPhase({ kind: "waiting-provider" });
|
|
12742
|
+
compactionInputSource = messagesText;
|
|
12743
|
+
compactionPrevSummarySource = existingSummary;
|
|
12744
|
+
compactionT0 = Date.now();
|
|
12745
|
+
const timeoutMs = typeof args2.timeoutMs === "number" && Number.isFinite(args2.timeoutMs) && args2.timeoutMs > 0 ? args2.timeoutMs : void 0;
|
|
12746
|
+
const requestController = new AbortController();
|
|
12747
|
+
let timeoutHandle;
|
|
12748
|
+
let abortListener;
|
|
12749
|
+
const request3 = provider.complete(
|
|
12750
|
+
[{ role: "system", content: COMPACTION_SUMMARY_SYSTEM_PROMPT }, { role: "user", content: promptContent }],
|
|
12751
|
+
{
|
|
12752
|
+
signal: requestController.signal,
|
|
12753
|
+
...timeoutMs ? { timeoutMs } : {},
|
|
12754
|
+
// 仅日志用的 attempt id:让 compaction 埋点与 transport 诊断日志 /
|
|
12755
|
+
// 服务端 x-request-id 可对上,用于关联请求级证据。不进 prompt/摘要/持久化。
|
|
12756
|
+
requestId: compactionAttemptId
|
|
12757
|
+
}
|
|
12758
|
+
).then(
|
|
12759
|
+
(value) => ({ kind: "done", value }),
|
|
12760
|
+
(error) => ({ kind: "provider-error", error })
|
|
12761
|
+
);
|
|
12762
|
+
const guards = [];
|
|
12763
|
+
if (timeoutMs) guards.push(new Promise((resolve5) => {
|
|
12764
|
+
timeoutHandle = setTimeout(() => {
|
|
12765
|
+
requestController.abort();
|
|
12766
|
+
resolve5({ kind: "timeout" });
|
|
12767
|
+
}, timeoutMs);
|
|
12768
|
+
}));
|
|
12769
|
+
if (args2.abortSignal) guards.push(new Promise((resolve5) => {
|
|
12770
|
+
abortListener = () => {
|
|
12771
|
+
requestController.abort(args2.abortSignal?.reason);
|
|
12772
|
+
resolve5({ kind: "aborted" });
|
|
12773
|
+
};
|
|
12774
|
+
args2.abortSignal?.addEventListener("abort", abortListener, { once: true });
|
|
12775
|
+
}));
|
|
12776
|
+
const outcome = guards.length ? await Promise.race([request3, ...guards]) : await request3;
|
|
12777
|
+
primaryElapsedMs = Date.now() - compactionT0;
|
|
12778
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
12779
|
+
if (abortListener) args2.abortSignal?.removeEventListener("abort", abortListener);
|
|
12780
|
+
if (outcome.kind !== "done") {
|
|
12781
|
+
const reason = outcome.kind === "timeout" ? "timeout" : outcome.kind === "aborted" ? "aborted" : "provider-error";
|
|
12782
|
+
const detail = outcome.kind === "provider-error" ? outcome.error instanceof Error ? outcome.error.message : String(outcome.error) : reason === "timeout" ? `auto-compaction timed out after ${timeoutMs}ms` : "auto-compaction aborted";
|
|
12783
|
+
throw Object.assign(new Error(detail), { compactionReason: reason });
|
|
12784
|
+
}
|
|
12785
|
+
const result4 = outcome.value;
|
|
12743
12786
|
const newSummary = typeof result4.content === "string" ? result4.content.trim() : "";
|
|
12744
12787
|
if (!newSummary) {
|
|
12745
12788
|
console.warn(
|
|
12746
12789
|
"[localLoop] auto-compaction produced empty summary; keeping prior projection"
|
|
12747
12790
|
);
|
|
12791
|
+
logCompactionTiming("empty", {});
|
|
12792
|
+
const failureReason = "provider-error";
|
|
12793
|
+
emitPhase({ kind: "compaction-failed", reason: failureReason });
|
|
12748
12794
|
return {
|
|
12749
12795
|
...projectExisting(),
|
|
12750
12796
|
failureMessage: "summary model returned empty content",
|
|
12797
|
+
failureReason,
|
|
12751
12798
|
decision: {
|
|
12752
12799
|
outcome: "failed",
|
|
12800
|
+
reason: failureReason,
|
|
12753
12801
|
detail: "summary model returned empty content"
|
|
12754
12802
|
}
|
|
12755
12803
|
};
|
|
12756
12804
|
}
|
|
12805
|
+
const saveT0 = Date.now();
|
|
12757
12806
|
await adapter.saveDialogSummary({
|
|
12758
12807
|
dialogId,
|
|
12759
12808
|
summary: newSummary,
|
|
@@ -12767,6 +12816,7 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
12767
12816
|
})(),
|
|
12768
12817
|
schemaVersion: COMPACTION_SUMMARY_SCHEMA_VERSION
|
|
12769
12818
|
});
|
|
12819
|
+
saveElapsedMs = Date.now() - saveT0;
|
|
12770
12820
|
const metricsReason = invalidSummary ? "invalid_summary" : coldResume ? "cold_resume" : "context_budget";
|
|
12771
12821
|
const metrics = buildCompactionMetricsFromPlan({
|
|
12772
12822
|
reason: metricsReason,
|
|
@@ -12776,6 +12826,11 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
12776
12826
|
summaryUsage: result4.usage
|
|
12777
12827
|
});
|
|
12778
12828
|
console.log(formatCompactionMetricsLog(metrics));
|
|
12829
|
+
logCompactionTiming("success", {
|
|
12830
|
+
model: result4?.model ?? args2.model ?? null,
|
|
12831
|
+
outputChars: newSummary.length
|
|
12832
|
+
});
|
|
12833
|
+
emitPhase({ kind: "compaction-end" });
|
|
12779
12834
|
return {
|
|
12780
12835
|
history: projectHistoryWithSummary({
|
|
12781
12836
|
history,
|
|
@@ -12803,10 +12858,14 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
12803
12858
|
} catch (error) {
|
|
12804
12859
|
console.warn("[localLoop] auto-compaction failed:", error);
|
|
12805
12860
|
const failureMessage = error instanceof Error && error.message ? error.message.slice(0, 200) : String(error).slice(0, 200);
|
|
12861
|
+
const failureReason = error instanceof Error && "compactionReason" in error ? error.compactionReason : "provider-error";
|
|
12862
|
+
logCompactionTiming(failureReason, {});
|
|
12863
|
+
emitPhase({ kind: "compaction-failed", reason: failureReason });
|
|
12806
12864
|
return {
|
|
12807
12865
|
...projectExisting(),
|
|
12808
12866
|
failureMessage,
|
|
12809
|
-
|
|
12867
|
+
failureReason,
|
|
12868
|
+
decision: { outcome: "failed", reason: failureReason, detail: failureMessage }
|
|
12810
12869
|
};
|
|
12811
12870
|
}
|
|
12812
12871
|
}
|
|
@@ -12863,6 +12922,8 @@ function emitLoopEvent(boundary, event, bridge) {
|
|
|
12863
12922
|
boundary.emit(bridge ? { event, bridge } : { event });
|
|
12864
12923
|
}
|
|
12865
12924
|
var LLM_REQUEST_TIMEOUT = "LLM_REQUEST_TIMEOUT";
|
|
12925
|
+
var DEFAULT_LLM_REQUEST_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
12926
|
+
var DEFAULT_COMPACTION_TIMEOUT_MS = 60 * 1e3;
|
|
12866
12927
|
var LOCAL_TURN_ABORTED_CODE = "LOCAL_TURN_ABORTED";
|
|
12867
12928
|
function buildAbortedError() {
|
|
12868
12929
|
const error = new Error("local agent turn aborted by user");
|
|
@@ -12890,8 +12951,11 @@ async function runAbortableToolTask(input, task, pendingToolName) {
|
|
|
12890
12951
|
}
|
|
12891
12952
|
function resolveLlmRequestTimeoutMs(input) {
|
|
12892
12953
|
const raw = input.llmRequestTimeoutMs ?? input.timeoutMs;
|
|
12893
|
-
|
|
12894
|
-
|
|
12954
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_LLM_REQUEST_TIMEOUT_MS;
|
|
12955
|
+
}
|
|
12956
|
+
function resolveCompactionTimeoutMs(input) {
|
|
12957
|
+
const raw = input.compactionTimeoutMs;
|
|
12958
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_COMPACTION_TIMEOUT_MS;
|
|
12895
12959
|
}
|
|
12896
12960
|
async function runCompleteWithTimeout(args2) {
|
|
12897
12961
|
const { provider, messages, options, timeoutMs, round, input, boundary, context: context3, providerName, model } = args2;
|
|
@@ -12914,6 +12978,7 @@ async function runCompleteWithTimeout(args2) {
|
|
|
12914
12978
|
const outcome = await runAbortableWithTimeout({
|
|
12915
12979
|
task: complete,
|
|
12916
12980
|
timeoutMs: typeof timeoutMs === "number" ? timeoutMs : void 0,
|
|
12981
|
+
activityVersion: args2.activityVersion,
|
|
12917
12982
|
abortSignal: input.abortSignal,
|
|
12918
12983
|
runtime: input.effectRuntime
|
|
12919
12984
|
});
|
|
@@ -12924,7 +12989,7 @@ async function runCompleteWithTimeout(args2) {
|
|
|
12924
12989
|
}
|
|
12925
12990
|
if (outcome.kind === "timeout") {
|
|
12926
12991
|
const timeoutError = new Error(
|
|
12927
|
-
`LLM request timed out after ${timeoutMs}ms (round ${round})`
|
|
12992
|
+
`LLM request timed out after ${timeoutMs}ms without new output (idle window, round ${round})`
|
|
12928
12993
|
);
|
|
12929
12994
|
timeoutError.code = LLM_REQUEST_TIMEOUT;
|
|
12930
12995
|
throw timeoutError;
|
|
@@ -12968,16 +13033,16 @@ async function runCompleteWithTimeout(args2) {
|
|
|
12968
13033
|
});
|
|
12969
13034
|
}
|
|
12970
13035
|
}
|
|
12971
|
-
function
|
|
13036
|
+
function clip(value, max4 = 240) {
|
|
12972
13037
|
return clipCompactText(value, max4);
|
|
12973
13038
|
}
|
|
12974
13039
|
function projectSafeToolObservationMetadata(metadata) {
|
|
12975
13040
|
if (!metadata || typeof metadata !== "object") return void 0;
|
|
12976
13041
|
const safe = {};
|
|
12977
13042
|
if (typeof metadata.exitCode === "number") safe.exitCode = metadata.exitCode;
|
|
12978
|
-
if (typeof metadata.actionGate === "string") safe.actionGate =
|
|
12979
|
-
if (typeof metadata.command === "string") safe.command =
|
|
12980
|
-
if (typeof metadata.path === "string") safe.path =
|
|
13043
|
+
if (typeof metadata.actionGate === "string") safe.actionGate = clip(metadata.actionGate, 240);
|
|
13044
|
+
if (typeof metadata.command === "string") safe.command = clip(metadata.command, 240);
|
|
13045
|
+
if (typeof metadata.path === "string") safe.path = clip(metadata.path, 240);
|
|
12981
13046
|
if (typeof metadata.truncated === "boolean") safe.truncated = metadata.truncated;
|
|
12982
13047
|
if (typeof metadata.byteCount === "number") safe.byteCount = metadata.byteCount;
|
|
12983
13048
|
if (typeof metadata.lineCount === "number") safe.lineCount = metadata.lineCount;
|
|
@@ -12993,7 +13058,7 @@ function summarizeToolResult(content, metadata) {
|
|
|
12993
13058
|
const lines = trimmed.split(/\r?\n/).length;
|
|
12994
13059
|
parts2.push(`${lines} line${lines === 1 ? "" : "s"}`);
|
|
12995
13060
|
parts2.push(`${trimmed.length} chars`);
|
|
12996
|
-
const tail =
|
|
13061
|
+
const tail = clip(trimmed.slice(-160), 160);
|
|
12997
13062
|
if (tail) parts2.push(`tail="${tail}"`);
|
|
12998
13063
|
} else {
|
|
12999
13064
|
parts2.push("empty");
|
|
@@ -13605,6 +13670,9 @@ async function runLocalAgentTurn(input) {
|
|
|
13605
13670
|
input.contextBlockScopes
|
|
13606
13671
|
);
|
|
13607
13672
|
const mergedContextBlockScopes = [
|
|
13673
|
+
// 删除安全红线:系统层最高优先级约束,位于所有块之前(含身份信息块),
|
|
13674
|
+
// owner 要求常驻「根本提示词」的最顶部(2026-09-26 批量误删事故)。
|
|
13675
|
+
{ content: DELETE_SAFETY_RED_LINE, cacheScope: "session" },
|
|
13608
13676
|
{ content: identityBlock, cacheScope: "session" },
|
|
13609
13677
|
...guidanceScopes,
|
|
13610
13678
|
...callerScopes
|
|
@@ -13637,6 +13705,16 @@ async function runLocalAgentTurn(input) {
|
|
|
13637
13705
|
}
|
|
13638
13706
|
}
|
|
13639
13707
|
let compactionUsage;
|
|
13708
|
+
const emitCompactionPhase = (phase, scope3) => {
|
|
13709
|
+
const atMs = Date.now();
|
|
13710
|
+
if (phase.kind === "validating-context") emitLoopEvent(observationBoundary, { kind: "turn-phase", phase: "validating-context", atMs, compactionScope: scope3 });
|
|
13711
|
+
else if (phase.kind === "compaction-start") {
|
|
13712
|
+
emitLoopEvent(observationBoundary, { kind: "turn-phase", phase: "compacting", atMs, compactionScope: scope3 });
|
|
13713
|
+
emitLoopEvent(observationBoundary, { kind: "compaction-start", atMs, scope: scope3 });
|
|
13714
|
+
} else if (phase.kind === "waiting-provider") emitLoopEvent(observationBoundary, { kind: "turn-phase", phase: "waiting-provider", atMs, compactionScope: scope3 });
|
|
13715
|
+
else if (phase.kind === "compaction-end") emitLoopEvent(observationBoundary, { kind: "compaction-end", atMs, scope: scope3 });
|
|
13716
|
+
else emitLoopEvent(observationBoundary, { kind: "compaction-failed", atMs, scope: scope3, reason: phase.reason });
|
|
13717
|
+
};
|
|
13640
13718
|
const emitCompactionObservation = (compacted) => {
|
|
13641
13719
|
const decision = compacted.decision;
|
|
13642
13720
|
if (decision?.outcome === "skipped") {
|
|
@@ -13670,7 +13748,10 @@ async function runLocalAgentTurn(input) {
|
|
|
13670
13748
|
model: agentConfig.model,
|
|
13671
13749
|
resolveProvider: resolveProviderOnce,
|
|
13672
13750
|
contextWindow,
|
|
13673
|
-
realContextUsagePercent
|
|
13751
|
+
realContextUsagePercent,
|
|
13752
|
+
abortSignal: input.abortSignal,
|
|
13753
|
+
timeoutMs: resolveCompactionTimeoutMs(input),
|
|
13754
|
+
onPhase: (phase) => emitCompactionPhase(phase, "initial")
|
|
13674
13755
|
});
|
|
13675
13756
|
history = compacted.history;
|
|
13676
13757
|
compactionUsage = compacted.usage;
|
|
@@ -13776,7 +13857,10 @@ async function runLocalAgentTurn(input) {
|
|
|
13776
13857
|
model: agentConfig.model,
|
|
13777
13858
|
resolveProvider: resolveProviderOnce,
|
|
13778
13859
|
contextWindow,
|
|
13779
|
-
...ratio !== void 0 ? { realContextUsagePercent: ratio } : {}
|
|
13860
|
+
...ratio !== void 0 ? { realContextUsagePercent: ratio } : {},
|
|
13861
|
+
abortSignal: input.abortSignal,
|
|
13862
|
+
timeoutMs: resolveCompactionTimeoutMs(input),
|
|
13863
|
+
onPhase: (phase) => emitCompactionPhase(phase, "in-loop")
|
|
13780
13864
|
});
|
|
13781
13865
|
if (compacted.usage) {
|
|
13782
13866
|
compactionUsage = addOutOfBandUsage(compactionUsage, compacted.usage);
|
|
@@ -13846,11 +13930,12 @@ async function runLocalAgentTurn(input) {
|
|
|
13846
13930
|
const shouldPassToolEvents = Boolean(
|
|
13847
13931
|
input.onToolEvent || input.onObservationEvent || input.observationBoundary
|
|
13848
13932
|
);
|
|
13933
|
+
let llmStreamActivity = 0;
|
|
13849
13934
|
result4 = await runCompleteWithTimeout({
|
|
13850
13935
|
provider,
|
|
13851
13936
|
messages: requestMessages,
|
|
13852
13937
|
options: {
|
|
13853
|
-
|
|
13938
|
+
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
13854
13939
|
// 用户取消信号穿进 provider options:providerStreamRetry 据此在
|
|
13855
13940
|
// 取消后跳过重试,provider 分支(如 antigravity/openai-compatible)
|
|
13856
13941
|
// 也可把 fetch 绑定到同一信号,实现真正的传输层取消。
|
|
@@ -13859,6 +13944,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13859
13944
|
// 归到具体对话而不是 chat-proxy 兜底桶。新对话首轮 id 尚未分配。
|
|
13860
13945
|
...input.continueDialogId ? { dialogId: input.continueDialogId } : {},
|
|
13861
13946
|
...shouldStreamDeltas ? { onTextDelta: (chunk) => {
|
|
13947
|
+
llmStreamActivity += 1;
|
|
13862
13948
|
partialContent += chunk;
|
|
13863
13949
|
observationBoundary.emit({
|
|
13864
13950
|
kind: "text-delta",
|
|
@@ -13868,6 +13954,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13868
13954
|
});
|
|
13869
13955
|
} } : {},
|
|
13870
13956
|
...shouldStreamReasoning ? { onReasoningDelta: (chunk) => {
|
|
13957
|
+
llmStreamActivity += 1;
|
|
13871
13958
|
observationBoundary.emit({
|
|
13872
13959
|
kind: "reasoning-delta",
|
|
13873
13960
|
chunk,
|
|
@@ -13876,6 +13963,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13876
13963
|
});
|
|
13877
13964
|
} } : {},
|
|
13878
13965
|
...shouldPassToolEvents ? { onToolEvent: (event) => {
|
|
13966
|
+
llmStreamActivity += 1;
|
|
13879
13967
|
observationBoundary.emit({
|
|
13880
13968
|
kind: "tool-event",
|
|
13881
13969
|
event,
|
|
@@ -13886,6 +13974,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13886
13974
|
...shouldPassToolEvents ? { toolEventRound: round } : {}
|
|
13887
13975
|
},
|
|
13888
13976
|
timeoutMs: resolveLlmRequestTimeoutMs(input),
|
|
13977
|
+
activityVersion: () => llmStreamActivity,
|
|
13889
13978
|
round,
|
|
13890
13979
|
input,
|
|
13891
13980
|
boundary: observationBoundary,
|
|
@@ -14357,33 +14446,6 @@ ${reasoningTailLog}
|
|
|
14357
14446
|
}
|
|
14358
14447
|
}
|
|
14359
14448
|
|
|
14360
|
-
// packages/agent-runtime/kimiUserAgent.ts
|
|
14361
|
-
var KIMI_CODE_CLI_VERSION = "0.29.2";
|
|
14362
|
-
var KIMI_CODE_USER_AGENT = `kimi-code-cli/${KIMI_CODE_CLI_VERSION} (nolo)`;
|
|
14363
|
-
function isKimiEndpoint(url) {
|
|
14364
|
-
return url.includes("api.kimi.com");
|
|
14365
|
-
}
|
|
14366
|
-
function kimiIdentityHeaders(url) {
|
|
14367
|
-
return isKimiEndpoint(url) ? { "User-Agent": KIMI_CODE_USER_AGENT } : {};
|
|
14368
|
-
}
|
|
14369
|
-
|
|
14370
|
-
// packages/agent-runtime/sseDataLine.ts
|
|
14371
|
-
function parseSseDataLineJson(line) {
|
|
14372
|
-
const trimmed = line.trim();
|
|
14373
|
-
if (!trimmed.startsWith("data:")) return null;
|
|
14374
|
-
const payload = trimmed.slice(5).trim();
|
|
14375
|
-
if (!payload || payload === "[DONE]") return null;
|
|
14376
|
-
try {
|
|
14377
|
-
return JSON.parse(payload);
|
|
14378
|
-
} catch {
|
|
14379
|
-
return null;
|
|
14380
|
-
}
|
|
14381
|
-
}
|
|
14382
|
-
function parseSseDataLineObject(line) {
|
|
14383
|
-
const parsed = parseSseDataLineJson(line);
|
|
14384
|
-
return parsed && typeof parsed === "object" ? parsed : null;
|
|
14385
|
-
}
|
|
14386
|
-
|
|
14387
14449
|
// packages/integrations/openai/responsesRequestBody.ts
|
|
14388
14450
|
function buildResponsesRequestBody(body, model) {
|
|
14389
14451
|
const tools = Array.isArray(body.tools) ? toResponsesTools(body.tools) : void 0;
|
|
@@ -14494,8 +14556,31 @@ function createResponsesStreamCollector(callbacks) {
|
|
|
14494
14556
|
};
|
|
14495
14557
|
const finalize2 = () => {
|
|
14496
14558
|
let finalToolCalls = finalizeResponsesToolCalls(toolCallsAcc);
|
|
14497
|
-
if (
|
|
14498
|
-
|
|
14559
|
+
if (completedResponse) {
|
|
14560
|
+
const completedToolCalls = extractToolCallsFromResponseOutput(completedResponse);
|
|
14561
|
+
const completedById = new Map(completedToolCalls.map((call) => [call.id, call]));
|
|
14562
|
+
finalToolCalls = finalToolCalls.map((call) => {
|
|
14563
|
+
const completed = completedById.get(call.id);
|
|
14564
|
+
if (!completed) return call;
|
|
14565
|
+
let accumulatedParses = false;
|
|
14566
|
+
let completedParses = false;
|
|
14567
|
+
try {
|
|
14568
|
+
JSON.parse(call.function.arguments);
|
|
14569
|
+
accumulatedParses = true;
|
|
14570
|
+
} catch {
|
|
14571
|
+
}
|
|
14572
|
+
try {
|
|
14573
|
+
JSON.parse(completed.function.arguments);
|
|
14574
|
+
completedParses = true;
|
|
14575
|
+
} catch {
|
|
14576
|
+
return call;
|
|
14577
|
+
}
|
|
14578
|
+
if (completedParses && (!accumulatedParses || completed.function.arguments.startsWith(call.function.arguments))) {
|
|
14579
|
+
return { ...call, function: { ...call.function, arguments: completed.function.arguments } };
|
|
14580
|
+
}
|
|
14581
|
+
return call;
|
|
14582
|
+
});
|
|
14583
|
+
if (finalToolCalls.length === 0) finalToolCalls = completedToolCalls;
|
|
14499
14584
|
}
|
|
14500
14585
|
if (!content && completedResponse) {
|
|
14501
14586
|
content = extractTextFromResponseOutput(completedResponse);
|
|
@@ -14562,6 +14647,7 @@ async function readResponsesSseCompletion(args2) {
|
|
|
14562
14647
|
}
|
|
14563
14648
|
|
|
14564
14649
|
// packages/agent-runtime/openAiCompatibleProvider.ts
|
|
14650
|
+
var REASONING_REPLAY_PLACEHOLDER = "(reasoning not captured for this turn)";
|
|
14565
14651
|
function isOpenAiResponsesEndpoint(endpoint) {
|
|
14566
14652
|
return endpoint.includes("/responses");
|
|
14567
14653
|
}
|
|
@@ -14575,9 +14661,14 @@ function buildOpenAiCompatibleChatCompletionRequest(args2) {
|
|
|
14575
14661
|
args2.providerConfig.provider,
|
|
14576
14662
|
args2.providerConfig.model
|
|
14577
14663
|
);
|
|
14664
|
+
const shouldReplayReasoning = shouldReplayReasoningContentForOutbound(
|
|
14665
|
+
args2.providerConfig.provider,
|
|
14666
|
+
args2.providerConfig.model
|
|
14667
|
+
);
|
|
14578
14668
|
const sanitizedMessages = sanitizeForOutbound(args2.messages, args2.tools);
|
|
14579
14669
|
const messages = toOpenAiCompatibleMessages(sanitizedMessages, {
|
|
14580
|
-
stripReasoningContent: shouldStripReasoning
|
|
14670
|
+
stripReasoningContent: shouldStripReasoning,
|
|
14671
|
+
...shouldReplayReasoning && !shouldStripReasoning ? { replayReasoningPlaceholder: REASONING_REPLAY_PLACEHOLDER } : {}
|
|
14581
14672
|
});
|
|
14582
14673
|
const rawBody = {
|
|
14583
14674
|
model: args2.providerConfig.model,
|
|
@@ -14606,9 +14697,9 @@ function buildOpenAiCompatibleChatCompletionRequest(args2) {
|
|
|
14606
14697
|
...buildProviderAuthHeaders({
|
|
14607
14698
|
endpoint,
|
|
14608
14699
|
apiKey: args2.providerConfig.apiKey,
|
|
14609
|
-
apiKeyHeader: args2.providerConfig.apiKeyHeader
|
|
14610
|
-
|
|
14611
|
-
|
|
14700
|
+
apiKeyHeader: args2.providerConfig.apiKeyHeader,
|
|
14701
|
+
sessionId: args2.sessionId
|
|
14702
|
+
})
|
|
14612
14703
|
};
|
|
14613
14704
|
return {
|
|
14614
14705
|
url: endpoint,
|
|
@@ -14711,7 +14802,8 @@ async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
|
14711
14802
|
providerConfig: apiKey2 === args2.providerConfig.apiKey ? args2.providerConfig : { ...args2.providerConfig, apiKey: apiKey2 },
|
|
14712
14803
|
messages: args2.messages,
|
|
14713
14804
|
tools: args2.tools,
|
|
14714
|
-
stream: args2.stream
|
|
14805
|
+
stream: args2.stream,
|
|
14806
|
+
sessionId: args2.sessionId
|
|
14715
14807
|
});
|
|
14716
14808
|
return args2.fetchImpl(request3.url, {
|
|
14717
14809
|
...request3.init,
|
|
@@ -16451,29 +16543,6 @@ function getProcessRegistry() {
|
|
|
16451
16543
|
return registry;
|
|
16452
16544
|
}
|
|
16453
16545
|
|
|
16454
|
-
// packages/agent-runtime/processOwnership.ts
|
|
16455
|
-
var asNonEmptyString = (value) => {
|
|
16456
|
-
if (typeof value !== "string") return null;
|
|
16457
|
-
const trimmed = value.trim();
|
|
16458
|
-
return trimmed ? trimmed : null;
|
|
16459
|
-
};
|
|
16460
|
-
function readProcessOwner(runtimeContext) {
|
|
16461
|
-
if (!runtimeContext || typeof runtimeContext !== "object") return null;
|
|
16462
|
-
const dialogId = asNonEmptyString(runtimeContext.dialogId) ?? asNonEmptyString(runtimeContext.parentThreadId);
|
|
16463
|
-
if (!dialogId) return null;
|
|
16464
|
-
const turnId = asNonEmptyString(runtimeContext.turnId);
|
|
16465
|
-
const ownerId = asNonEmptyString(runtimeContext.ownerId);
|
|
16466
|
-
return {
|
|
16467
|
-
dialogId,
|
|
16468
|
-
...turnId ? { turnId } : {},
|
|
16469
|
-
...ownerId ? { ownerId } : {}
|
|
16470
|
-
};
|
|
16471
|
-
}
|
|
16472
|
-
|
|
16473
|
-
// packages/agent-runtime/workspaceShell.ts
|
|
16474
|
-
import { resolve as resolve3 } from "node:path";
|
|
16475
|
-
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
16476
|
-
|
|
16477
16546
|
// packages/agent-runtime/processTaskResult.ts
|
|
16478
16547
|
var PROCESS_RESULT_CAPSULE_TAIL_CHARS = 4e3;
|
|
16479
16548
|
var PROCESS_RESULT_CAPSULE_SPILL_THRESHOLD_CHARS = 2e4;
|
|
@@ -16493,11 +16562,17 @@ function buildProcessTaskResultCapsule(args2) {
|
|
|
16493
16562
|
const exitCode = args2.exitCode;
|
|
16494
16563
|
const captureError = args2.captureError?.trim() || void 0;
|
|
16495
16564
|
const durationMs = typeof args2.startedAt === "number" && Number.isFinite(args2.startedAt) ? Math.max(0, (args2.endedAt ?? Date.now()) - args2.startedAt) : void 0;
|
|
16496
|
-
const
|
|
16497
|
-
const
|
|
16565
|
+
const stdoutProvenance = args2.streamProvenance?.stdout;
|
|
16566
|
+
const stderrProvenance = args2.streamProvenance?.stderr;
|
|
16567
|
+
const ringEvicted = Boolean(stdoutProvenance?.evicted || stderrProvenance?.evicted);
|
|
16568
|
+
const stdoutTailSource = typeof args2.stdoutTail === "string" ? args2.stdoutTail : stdout;
|
|
16569
|
+
const stderrTailSource = typeof args2.stderrTail === "string" ? args2.stderrTail : stderr;
|
|
16570
|
+
const stdoutTail = tailText(stdoutTailSource, tailChars);
|
|
16571
|
+
const stderrTail = tailText(stderrTailSource, tailChars);
|
|
16498
16572
|
const inlineSize = stdout.length + stderr.length;
|
|
16499
16573
|
const inlineTruncated = stdoutTail.truncated || stderrTail.truncated;
|
|
16500
|
-
const
|
|
16574
|
+
const truncated = inlineTruncated || ringEvicted || Boolean(captureError);
|
|
16575
|
+
const shouldSpill = truncated || inlineSize > spillThresholdChars;
|
|
16501
16576
|
let spill;
|
|
16502
16577
|
if (shouldSpill) {
|
|
16503
16578
|
try {
|
|
@@ -16511,8 +16586,11 @@ function buildProcessTaskResultCapsule(args2) {
|
|
|
16511
16586
|
});
|
|
16512
16587
|
spill = {
|
|
16513
16588
|
displayPath: result4.displayPath,
|
|
16514
|
-
|
|
16515
|
-
|
|
16589
|
+
// Prefer the caller's live provenance counters: they count every
|
|
16590
|
+
// byte of the original stream, while the buffered content above may
|
|
16591
|
+
// be a capped prefix of it.
|
|
16592
|
+
totalChars: (stdoutProvenance?.totalChars ?? stdout.length) + (stderrProvenance?.totalChars ?? stderr.length),
|
|
16593
|
+
totalLines: (stdoutProvenance?.totalLines ?? countLines(stdout)) + (stderrProvenance?.totalLines ?? countLines(stderr))
|
|
16516
16594
|
};
|
|
16517
16595
|
} catch {
|
|
16518
16596
|
}
|
|
@@ -16523,12 +16601,33 @@ function buildProcessTaskResultCapsule(args2) {
|
|
|
16523
16601
|
exitCode,
|
|
16524
16602
|
...durationMs !== void 0 ? { durationMs } : {},
|
|
16525
16603
|
...captureError ? { captureError } : {},
|
|
16526
|
-
truncated
|
|
16604
|
+
truncated,
|
|
16527
16605
|
...spill ? { spill } : {}
|
|
16528
16606
|
};
|
|
16529
16607
|
}
|
|
16530
16608
|
|
|
16609
|
+
// packages/agent-runtime/processOwnership.ts
|
|
16610
|
+
var asNonEmptyString = (value) => {
|
|
16611
|
+
if (typeof value !== "string") return null;
|
|
16612
|
+
const trimmed = value.trim();
|
|
16613
|
+
return trimmed ? trimmed : null;
|
|
16614
|
+
};
|
|
16615
|
+
function readProcessOwner(runtimeContext) {
|
|
16616
|
+
if (!runtimeContext || typeof runtimeContext !== "object") return null;
|
|
16617
|
+
const dialogId = asNonEmptyString(runtimeContext.dialogId) ?? asNonEmptyString(runtimeContext.parentThreadId);
|
|
16618
|
+
if (!dialogId) return null;
|
|
16619
|
+
const turnId = asNonEmptyString(runtimeContext.turnId);
|
|
16620
|
+
const ownerId = asNonEmptyString(runtimeContext.ownerId);
|
|
16621
|
+
return {
|
|
16622
|
+
dialogId,
|
|
16623
|
+
...turnId ? { turnId } : {},
|
|
16624
|
+
...ownerId ? { ownerId } : {}
|
|
16625
|
+
};
|
|
16626
|
+
}
|
|
16627
|
+
|
|
16531
16628
|
// packages/agent-runtime/workspaceShell.ts
|
|
16629
|
+
import { resolve as resolve3 } from "node:path";
|
|
16630
|
+
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
16532
16631
|
var EXEC_SHELL_TIMEOUT_ENV = "NOLO_EXEC_SHELL_TIMEOUT_MS";
|
|
16533
16632
|
var EXEC_SHELL_DETACH_ENV = "NOLO_EXEC_SHELL_DETACH_MS";
|
|
16534
16633
|
var DEFAULT_EXEC_SHELL_DETACH_MS = 12e4;
|
|
@@ -17397,13 +17496,169 @@ function runTasks(args2) {
|
|
|
17397
17496
|
return { tasks, count: tasks.length };
|
|
17398
17497
|
}
|
|
17399
17498
|
|
|
17499
|
+
// packages/agent-runtime/execShellCompletionWarnings.ts
|
|
17500
|
+
var BG_ESCAPE_WORD_PATTERN = /(?:^|[\s;|(&/\\])(nohup|disown|setsid|start-process)(?=$|[\s;|)&])/i;
|
|
17501
|
+
var SHELL_SPLIT_CHARS = /* @__PURE__ */ new Set([";", "|", "&", "(", ")", "<", ">", "\n", " ", " "]);
|
|
17502
|
+
function maskQuotedAndEscaped(command) {
|
|
17503
|
+
const out = Array.from(command);
|
|
17504
|
+
let quote = null;
|
|
17505
|
+
for (let i = 0; i < out.length; i += 1) {
|
|
17506
|
+
const ch = out[i];
|
|
17507
|
+
if (quote) {
|
|
17508
|
+
out[i] = " ";
|
|
17509
|
+
if (ch === "\\" && quote !== "'") {
|
|
17510
|
+
if (i + 1 < out.length) out[i + 1] = " ";
|
|
17511
|
+
i += 1;
|
|
17512
|
+
} else if (ch === quote) {
|
|
17513
|
+
quote = null;
|
|
17514
|
+
}
|
|
17515
|
+
continue;
|
|
17516
|
+
}
|
|
17517
|
+
if (ch === "\\") {
|
|
17518
|
+
out[i] = " ";
|
|
17519
|
+
if (i + 1 < out.length) out[i + 1] = " ";
|
|
17520
|
+
i += 1;
|
|
17521
|
+
continue;
|
|
17522
|
+
}
|
|
17523
|
+
if (ch === "'" || ch === '"' || ch === "`") {
|
|
17524
|
+
quote = ch;
|
|
17525
|
+
out[i] = " ";
|
|
17526
|
+
continue;
|
|
17527
|
+
}
|
|
17528
|
+
if (ch === "#" && (i === 0 || /[\s;]/.test(out[i - 1] ?? " "))) {
|
|
17529
|
+
while (i < out.length && out[i] !== "\n") {
|
|
17530
|
+
out[i] = " ";
|
|
17531
|
+
i += 1;
|
|
17532
|
+
}
|
|
17533
|
+
}
|
|
17534
|
+
}
|
|
17535
|
+
return out.join("");
|
|
17536
|
+
}
|
|
17537
|
+
function readRedirectTarget(original, start) {
|
|
17538
|
+
let i = start;
|
|
17539
|
+
while (i < original.length && /\s/.test(original[i] ?? "")) {
|
|
17540
|
+
i += 1;
|
|
17541
|
+
}
|
|
17542
|
+
if (i >= original.length) return void 0;
|
|
17543
|
+
let text = "";
|
|
17544
|
+
let j = i;
|
|
17545
|
+
while (j < original.length) {
|
|
17546
|
+
const o = original[j];
|
|
17547
|
+
if (o === "'" || o === '"' || o === "`") {
|
|
17548
|
+
const quote = o;
|
|
17549
|
+
j += 1;
|
|
17550
|
+
while (j < original.length && original[j] !== quote) {
|
|
17551
|
+
if (original[j] === "\\" && quote !== "'" && j + 1 < original.length) {
|
|
17552
|
+
text += original[j + 1];
|
|
17553
|
+
j += 2;
|
|
17554
|
+
continue;
|
|
17555
|
+
}
|
|
17556
|
+
text += original[j];
|
|
17557
|
+
j += 1;
|
|
17558
|
+
}
|
|
17559
|
+
j += 1;
|
|
17560
|
+
continue;
|
|
17561
|
+
}
|
|
17562
|
+
if (/\s/.test(o) || SHELL_SPLIT_CHARS.has(o)) break;
|
|
17563
|
+
text += o;
|
|
17564
|
+
j += 1;
|
|
17565
|
+
}
|
|
17566
|
+
if (!text || text === "$") return void 0;
|
|
17567
|
+
return { text, end: j };
|
|
17568
|
+
}
|
|
17569
|
+
function isIgnoredRedirectTarget(target) {
|
|
17570
|
+
return target === "/dev/null";
|
|
17571
|
+
}
|
|
17572
|
+
function detectExecShellSynchronousWarnings(command, shell) {
|
|
17573
|
+
const masked = maskQuotedAndEscaped(command);
|
|
17574
|
+
const isPowerShell = shell?.resolvedShell === "powershell";
|
|
17575
|
+
const redirectTargets = [];
|
|
17576
|
+
let backgrounded = false;
|
|
17577
|
+
let i = 0;
|
|
17578
|
+
while (i < masked.length) {
|
|
17579
|
+
const ch = masked[i];
|
|
17580
|
+
if (ch === "&") {
|
|
17581
|
+
const next = masked[i + 1];
|
|
17582
|
+
if (next === "&") {
|
|
17583
|
+
i += 2;
|
|
17584
|
+
continue;
|
|
17585
|
+
}
|
|
17586
|
+
if (next === ">") {
|
|
17587
|
+
let j = i + 2;
|
|
17588
|
+
if (masked[j] === ">") j += 1;
|
|
17589
|
+
const target = readRedirectTarget(command, j);
|
|
17590
|
+
if (target && !isIgnoredRedirectTarget(target.text)) redirectTargets.push(target.text);
|
|
17591
|
+
i = target ? target.end : j;
|
|
17592
|
+
continue;
|
|
17593
|
+
}
|
|
17594
|
+
const prev = masked[i - 1];
|
|
17595
|
+
if (prev === ">" || prev === "<") {
|
|
17596
|
+
i += 1;
|
|
17597
|
+
continue;
|
|
17598
|
+
}
|
|
17599
|
+
if (isPowerShell) {
|
|
17600
|
+
i += 1;
|
|
17601
|
+
continue;
|
|
17602
|
+
}
|
|
17603
|
+
backgrounded = true;
|
|
17604
|
+
i += 1;
|
|
17605
|
+
continue;
|
|
17606
|
+
}
|
|
17607
|
+
if (ch === ">") {
|
|
17608
|
+
const prev = masked[i - 1];
|
|
17609
|
+
if (prev === ">" || prev === "&" || prev === "<") {
|
|
17610
|
+
i += 1;
|
|
17611
|
+
continue;
|
|
17612
|
+
}
|
|
17613
|
+
let j = i + 1;
|
|
17614
|
+
if (masked[j] === ">") j += 1;
|
|
17615
|
+
if (masked[j] === "&") {
|
|
17616
|
+
const ampTarget = readRedirectTarget(command, j + 1);
|
|
17617
|
+
const isFdDuplication = ampTarget !== void 0 && (/^\d+$/.test(ampTarget.text) || ampTarget.text === "-");
|
|
17618
|
+
if (ampTarget && !isFdDuplication && !isIgnoredRedirectTarget(ampTarget.text)) {
|
|
17619
|
+
redirectTargets.push(ampTarget.text);
|
|
17620
|
+
}
|
|
17621
|
+
i = ampTarget ? ampTarget.end : j + 1;
|
|
17622
|
+
continue;
|
|
17623
|
+
}
|
|
17624
|
+
const target = readRedirectTarget(command, j);
|
|
17625
|
+
if (target && !isIgnoredRedirectTarget(target.text)) redirectTargets.push(target.text);
|
|
17626
|
+
i = target ? target.end : j;
|
|
17627
|
+
continue;
|
|
17628
|
+
}
|
|
17629
|
+
if (ch === "<") {
|
|
17630
|
+
i += masked[i + 1] === "<" || masked[i + 1] === "&" ? 2 : 1;
|
|
17631
|
+
continue;
|
|
17632
|
+
}
|
|
17633
|
+
i += 1;
|
|
17634
|
+
}
|
|
17635
|
+
const wordMatch = BG_ESCAPE_WORD_PATTERN.exec(masked);
|
|
17636
|
+
if (wordMatch) backgrounded = true;
|
|
17637
|
+
const warnings = [];
|
|
17638
|
+
if (redirectTargets.length > 0) {
|
|
17639
|
+
const target = redirectTargets[0];
|
|
17640
|
+
warnings.push({
|
|
17641
|
+
kind: "output-redirect",
|
|
17642
|
+
redirectTarget: target,
|
|
17643
|
+
message: `[wake-safety] This execShell call completed synchronously; its output was redirected to ${target}. That file is NOT delivered by any completion notification \u2014 no tracked background task was created. If you need the result, read that file in this turn.`
|
|
17644
|
+
});
|
|
17645
|
+
}
|
|
17646
|
+
if (backgrounded) {
|
|
17647
|
+
warnings.push({
|
|
17648
|
+
kind: "shell-backgrounding",
|
|
17649
|
+
message: `[wake-safety] Detected shell-internal backgrounding (lone \`&\`, nohup/disown/setsid/Start-Process or similar). Descendant processes are NOT tracked as platform tasks and will not produce completion notifications; text such as \`LAUNCHED\` printed by the command is plain stdout, not a platform receipt.`
|
|
17650
|
+
});
|
|
17651
|
+
}
|
|
17652
|
+
return warnings;
|
|
17653
|
+
}
|
|
17654
|
+
|
|
17400
17655
|
// packages/agent-runtime/capabilities/execShellCapability.ts
|
|
17401
17656
|
function buildExecShellToolDefinition(toolName = "execShell") {
|
|
17402
17657
|
return {
|
|
17403
17658
|
type: "function",
|
|
17404
17659
|
function: {
|
|
17405
17660
|
name: toolName,
|
|
17406
|
-
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. On Windows the resolved shell may be Windows PowerShell 5.1 (metadata.shellKind="powershell5"): it does not support '&&'/'||' or $PSStyle \u2014 join commands with ';' or split into multiple calls. metadata.shellKind="pwsh" means PowerShell 7+ with full syntax. Read resolvedShell/shellKind from any execShell result before writing Windows-specific syntax.`,
|
|
17661
|
+
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. On Windows the resolved shell may be Windows PowerShell 5.1 (metadata.shellKind="powershell5"): it does not support '&&'/'||' or $PSStyle \u2014 join commands with ';' or split into multiple calls. metadata.shellKind="pwsh" means PowerShell 7+ with full syntax. Read resolvedShell/shellKind from any execShell result before writing Windows-specific syntax. LIFECYCLE CONTRACT (misreading this contract silenced a real dialog for 10 hours): (1) A normal command waits synchronously for at most 120 seconds; if it ends inside that window the call IS finished \u2014 a result containing exitCode means the command has already completed, never "still running". (2) Only a result with metadata.detached === true AND a taskId represents a tracked background task that may trigger completion wake-up (terminal completion turn carrying a bounded result capsule); that handle may be waited on with taskWait and will produce a completion notification. (3) Text the command itself prints (LAUNCHED, STARTED, BACKGROUND, ...) 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 immediately. When a synchronous result's core output was redirected to a file, read that file in the SAME turn \u2014 never end the turn promising a later automatic report without a taskId.`,
|
|
17407
17662
|
parameters: {
|
|
17408
17663
|
type: "object",
|
|
17409
17664
|
properties: {
|
|
@@ -17414,6 +17669,10 @@ function buildExecShellToolDefinition(toolName = "execShell") {
|
|
|
17414
17669
|
cmd: {
|
|
17415
17670
|
type: "string",
|
|
17416
17671
|
description: "Compatibility alias for command."
|
|
17672
|
+
},
|
|
17673
|
+
background: {
|
|
17674
|
+
type: "boolean",
|
|
17675
|
+
description: "Immediately detach this command into a tracked background task (no 120s synchronous wait): returns {detached: true, taskId}, and on completion the platform resumes this conversation with a bounded result capsule (exitCode, duration, stdout/stderr tail). Default false. Use for finite jobs (tests, builds, batch) whose result you need later; NOT for dev servers/watchers \u2014 use launchProcess for those."
|
|
17417
17676
|
}
|
|
17418
17677
|
}
|
|
17419
17678
|
}
|
|
@@ -17454,11 +17713,13 @@ function normalizeExecShellInput(input) {
|
|
|
17454
17713
|
throw new Error("execShell requires a non-empty command.");
|
|
17455
17714
|
}
|
|
17456
17715
|
const activity = extractActivity(record);
|
|
17716
|
+
const background = record.background === true || typeof record.background === "string" && record.background.trim().toLowerCase() === "true";
|
|
17457
17717
|
return {
|
|
17458
17718
|
command,
|
|
17459
17719
|
...record.shell !== void 0 ? { shell: record.shell } : {},
|
|
17460
17720
|
...activity ? { activity } : {},
|
|
17461
|
-
...record.input !== void 0 ? { input: record.input } : {}
|
|
17721
|
+
...record.input !== void 0 ? { input: record.input } : {},
|
|
17722
|
+
...background ? { background: true } : {}
|
|
17462
17723
|
};
|
|
17463
17724
|
}
|
|
17464
17725
|
throw new Error("execShell requires a non-empty command.");
|
|
@@ -17496,6 +17757,7 @@ var execShellCapability = {
|
|
|
17496
17757
|
command,
|
|
17497
17758
|
shell: normalized.shell
|
|
17498
17759
|
});
|
|
17760
|
+
const background = normalized.background === true;
|
|
17499
17761
|
const result4 = await runWorkspaceCommand({
|
|
17500
17762
|
workspaceRoot,
|
|
17501
17763
|
command: shellPlan.argv,
|
|
@@ -17503,15 +17765,18 @@ var execShellCapability = {
|
|
|
17503
17765
|
outputLimit: ctx.commandOutputLimit,
|
|
17504
17766
|
commandPrefix: ctx.commandPrefix,
|
|
17505
17767
|
abortSignal: ctx.abortSignal,
|
|
17506
|
-
detachMs: isImmediateDetachShellCommand({ command }) ? 0 : ctx.detachMs,
|
|
17768
|
+
detachMs: background ? 0 : isImmediateDetachShellCommand({ command }) ? 0 : ctx.detachMs,
|
|
17507
17769
|
stdin: typeof normalized.input === "string" ? normalized.input : void 0,
|
|
17508
17770
|
// Ownership of the turn that invoked this command: an auto-detached
|
|
17509
17771
|
// command keeps its parent dialog so its terminal can resume that
|
|
17510
17772
|
// conversation (see processOwnership.ts). Absent ctx.owner = unowned.
|
|
17511
17773
|
owner: ctx.owner ?? null
|
|
17512
17774
|
});
|
|
17775
|
+
const warnings = result4.detached || result4.spawnFailed ? [] : detectExecShellSynchronousWarnings(command, {
|
|
17776
|
+
resolvedShell: shellPlan.resolvedShell
|
|
17777
|
+
});
|
|
17513
17778
|
return {
|
|
17514
|
-
content: result4.content,
|
|
17779
|
+
content: warnings.length > 0 ? [result4.content, ...warnings.map((warning) => warning.message)].join("\n\n") : result4.content,
|
|
17515
17780
|
metadata: {
|
|
17516
17781
|
command,
|
|
17517
17782
|
exitCode: result4.exitCode,
|
|
@@ -17526,8 +17791,21 @@ var execShellCapability = {
|
|
|
17526
17791
|
// Phase 0: stable taskId from the pre-registered Execution
|
|
17527
17792
|
// Envelope (additive; existing detached fields untouched).
|
|
17528
17793
|
taskId: result4.taskId,
|
|
17529
|
-
status: "running"
|
|
17530
|
-
|
|
17794
|
+
status: "running",
|
|
17795
|
+
// P0 machine-readable execution state: an explicit positive
|
|
17796
|
+
// signal instead of requiring the model to infer "not detached"
|
|
17797
|
+
// from absence. Mirrors the real lifecycle contract.
|
|
17798
|
+
executionState: "detached",
|
|
17799
|
+
trackedBackgroundTask: true,
|
|
17800
|
+
completionNotification: "terminal-resume"
|
|
17801
|
+
} : {
|
|
17802
|
+
// P0 machine-readable execution state: the command already
|
|
17803
|
+
// finished inside the synchronous window; no background task
|
|
17804
|
+
// exists, so no completion notification will ever arrive.
|
|
17805
|
+
executionState: "synchronous-complete",
|
|
17806
|
+
trackedBackgroundTask: false,
|
|
17807
|
+
completionNotification: "none"
|
|
17808
|
+
},
|
|
17531
17809
|
...normalized.activity ? { activity: normalized.activity } : {}
|
|
17532
17810
|
}
|
|
17533
17811
|
};
|
|
@@ -17743,7 +18021,7 @@ function buildLaunchProcessTool() {
|
|
|
17743
18021
|
type: "function",
|
|
17744
18022
|
function: {
|
|
17745
18023
|
name: "launchProcess",
|
|
17746
|
-
description: "Start a long-running background process (dev server, watcher, REPL) and return immediately with {pid, label, status}. Use listProcesses to inspect or stop it.",
|
|
18024
|
+
description: "Start a long-running ambient background process (dev server, watcher, REPL) and return immediately with {pid, label, taskId, status}. Real boundaries: this registers a tracked background task, but completion does NOT automatically start a new turn \u2014 the process is intentionally notice-only (an exited dev server must not silently burn a model turn). When it reaches a terminal state the bounded result (exitCode, duration, stdout/stderr tail) is recorded and surfaced as a notice injected only on your next real turn in the same conversation. Use listProcesses to inspect, taskWait to block for its terminal state, or taskStop to stop it. For a finite job (tests, builds, batch) whose result must resume the conversation automatically, use execShell with background: true instead.",
|
|
17747
18025
|
parameters: {
|
|
17748
18026
|
type: "object",
|
|
17749
18027
|
properties: {
|
|
@@ -18529,6 +18807,87 @@ async function writeFileTool(args2) {
|
|
|
18529
18807
|
}
|
|
18530
18808
|
};
|
|
18531
18809
|
}
|
|
18810
|
+
function extractSnippetWords(text) {
|
|
18811
|
+
const tokens = [];
|
|
18812
|
+
const latinWords = text.match(/[A-Za-z0-9_]{2,}/g);
|
|
18813
|
+
if (latinWords) {
|
|
18814
|
+
for (const w of latinWords) tokens.push(w.toLowerCase());
|
|
18815
|
+
}
|
|
18816
|
+
const cjkChars = text.match(new RegExp("\\p{Script=Han}", "gu"));
|
|
18817
|
+
if (cjkChars) {
|
|
18818
|
+
for (let i = 0; i < cjkChars.length - 1; i++) {
|
|
18819
|
+
tokens.push(cjkChars[i] + cjkChars[i + 1]);
|
|
18820
|
+
}
|
|
18821
|
+
if (cjkChars.length === 1) tokens.push(cjkChars[0]);
|
|
18822
|
+
}
|
|
18823
|
+
return tokens;
|
|
18824
|
+
}
|
|
18825
|
+
function calculateEditLineSimilarity(a, b) {
|
|
18826
|
+
if (a === b) return 1;
|
|
18827
|
+
if (!a || !b) return 0;
|
|
18828
|
+
if (a.includes(b) || b.includes(a)) return 0.8;
|
|
18829
|
+
const wordsA = extractSnippetWords(a);
|
|
18830
|
+
const wordsB = extractSnippetWords(b);
|
|
18831
|
+
if (wordsA.length === 0 || wordsB.length === 0) return 0;
|
|
18832
|
+
const setB = new Set(wordsB);
|
|
18833
|
+
let matches = 0;
|
|
18834
|
+
for (const w of wordsA) {
|
|
18835
|
+
if (setB.has(w)) matches++;
|
|
18836
|
+
}
|
|
18837
|
+
return 2 * matches / (wordsA.length + wordsB.length);
|
|
18838
|
+
}
|
|
18839
|
+
function findClosestEditSnippet(content, oldText) {
|
|
18840
|
+
const contentLines = content.split(/\r?\n/);
|
|
18841
|
+
const oldLinesRaw = oldText.split(/\r?\n/);
|
|
18842
|
+
const oldTrimmedLines = oldLinesRaw.map((l) => l.trim()).filter(Boolean);
|
|
18843
|
+
if (contentLines.length === 0 || oldTrimmedLines.length === 0) return null;
|
|
18844
|
+
if (oldTrimmedLines.length > 0 && contentLines.length >= oldTrimmedLines.length) {
|
|
18845
|
+
for (let i = 0; i <= contentLines.length - oldTrimmedLines.length; i++) {
|
|
18846
|
+
let allMatch = true;
|
|
18847
|
+
for (let j = 0; j < oldTrimmedLines.length; j++) {
|
|
18848
|
+
if (contentLines[i + j].trim() !== oldTrimmedLines[j]) {
|
|
18849
|
+
allMatch = false;
|
|
18850
|
+
break;
|
|
18851
|
+
}
|
|
18852
|
+
}
|
|
18853
|
+
if (allMatch) {
|
|
18854
|
+
const startLine2 = i + 1;
|
|
18855
|
+
const endLine2 = i + oldTrimmedLines.length;
|
|
18856
|
+
const snippetLines2 = [];
|
|
18857
|
+
for (let k = i; k < i + oldTrimmedLines.length; k++) {
|
|
18858
|
+
snippetLines2.push(`> ${k + 1}: ${contentLines[k]}`);
|
|
18859
|
+
}
|
|
18860
|
+
return `Exact match found with different indentation/whitespace (lines ${startLine2}-${endLine2}):
|
|
18861
|
+
${snippetLines2.join("\n")}`;
|
|
18862
|
+
}
|
|
18863
|
+
}
|
|
18864
|
+
}
|
|
18865
|
+
const candidateTargetLines = oldTrimmedLines.filter((l) => l.length >= 4);
|
|
18866
|
+
const targetLine = candidateTargetLines[0] || oldTrimmedLines[0];
|
|
18867
|
+
if (!targetLine || targetLine.length < 3) return null;
|
|
18868
|
+
let bestIndex = -1;
|
|
18869
|
+
let bestScore = 0;
|
|
18870
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
18871
|
+
const line = contentLines[i].trim();
|
|
18872
|
+
if (!line || line.length < 3) continue;
|
|
18873
|
+
const score = calculateEditLineSimilarity(line, targetLine);
|
|
18874
|
+
if (score > bestScore && score >= 0.45) {
|
|
18875
|
+
bestScore = score;
|
|
18876
|
+
bestIndex = i;
|
|
18877
|
+
if (score === 1) break;
|
|
18878
|
+
}
|
|
18879
|
+
}
|
|
18880
|
+
if (bestIndex === -1) return null;
|
|
18881
|
+
const startLine = Math.max(0, bestIndex - 2);
|
|
18882
|
+
const endLine = Math.min(contentLines.length - 1, bestIndex + 2);
|
|
18883
|
+
const snippetLines = [];
|
|
18884
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
18885
|
+
const prefix = i === bestIndex ? "> " : " ";
|
|
18886
|
+
snippetLines.push(`${prefix}${i + 1}: ${contentLines[i]}`);
|
|
18887
|
+
}
|
|
18888
|
+
return `Closest match near line ${bestIndex + 1}:
|
|
18889
|
+
${snippetLines.join("\n")}`;
|
|
18890
|
+
}
|
|
18532
18891
|
async function editFileTool(args2) {
|
|
18533
18892
|
const parsed = parseWorkspaceToolArguments(args2.call.arguments);
|
|
18534
18893
|
const requestedPath = requireWorkspaceToolPath(parsed);
|
|
@@ -18547,8 +18906,11 @@ async function editFileTool(args2) {
|
|
|
18547
18906
|
newText
|
|
18548
18907
|
});
|
|
18549
18908
|
if (replacementCount !== expectedReplacements) {
|
|
18909
|
+
const hint = replacementCount === 0 ? findClosestEditSnippet(content, oldText) : null;
|
|
18550
18910
|
throw new Error(
|
|
18551
|
-
`editFile expected ${expectedReplacements} ${pluralizeReplacement(expectedReplacements)} but found ${replacementCount} in ${requestedPath} (matched after EOL normalization; verify the exact text).`
|
|
18911
|
+
`editFile expected ${expectedReplacements} ${pluralizeReplacement(expectedReplacements)} but found ${replacementCount} in ${requestedPath} (matched after EOL normalization; verify the exact text).` + (hint ? `
|
|
18912
|
+
|
|
18913
|
+
${hint}` : "")
|
|
18552
18914
|
);
|
|
18553
18915
|
}
|
|
18554
18916
|
await writeFile(absolutePath, nextContent, "utf8");
|
|
@@ -18884,6 +19246,55 @@ async function execShellTool(args2) {
|
|
|
18884
19246
|
}
|
|
18885
19247
|
);
|
|
18886
19248
|
}
|
|
19249
|
+
var LAUNCH_PROCESS_STREAM_RING_CHARS = 65536;
|
|
19250
|
+
var LAUNCH_PROCESS_STREAM_CAPTURE_MAX_CHARS = 4e6;
|
|
19251
|
+
function createLaunchProcessStreamCapture() {
|
|
19252
|
+
let ring = "";
|
|
19253
|
+
let full = null;
|
|
19254
|
+
let capturedChars = 0;
|
|
19255
|
+
let totalChars = 0;
|
|
19256
|
+
let totalNewlines = 0;
|
|
19257
|
+
return {
|
|
19258
|
+
push(chunk) {
|
|
19259
|
+
const str = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
19260
|
+
if (!str) return;
|
|
19261
|
+
totalChars += str.length;
|
|
19262
|
+
for (let i = 0; i < str.length; i += 1) {
|
|
19263
|
+
if (str.charCodeAt(i) === 10) totalNewlines += 1;
|
|
19264
|
+
}
|
|
19265
|
+
const combined = ring + str;
|
|
19266
|
+
if (combined.length <= LAUNCH_PROCESS_STREAM_RING_CHARS) {
|
|
19267
|
+
ring = combined;
|
|
19268
|
+
return;
|
|
19269
|
+
}
|
|
19270
|
+
if (full === null) {
|
|
19271
|
+
full = [combined];
|
|
19272
|
+
capturedChars = combined.length;
|
|
19273
|
+
} else if (capturedChars < LAUNCH_PROCESS_STREAM_CAPTURE_MAX_CHARS) {
|
|
19274
|
+
const room = LAUNCH_PROCESS_STREAM_CAPTURE_MAX_CHARS - capturedChars;
|
|
19275
|
+
const slice = str.length <= room ? str : str.slice(0, room);
|
|
19276
|
+
full.push(slice);
|
|
19277
|
+
capturedChars += slice.length;
|
|
19278
|
+
}
|
|
19279
|
+
ring = combined.slice(-LAUNCH_PROCESS_STREAM_RING_CHARS);
|
|
19280
|
+
},
|
|
19281
|
+
text() {
|
|
19282
|
+
return full === null ? ring : full.join("");
|
|
19283
|
+
},
|
|
19284
|
+
tailText() {
|
|
19285
|
+
return ring;
|
|
19286
|
+
},
|
|
19287
|
+
evicted() {
|
|
19288
|
+
return full !== null;
|
|
19289
|
+
},
|
|
19290
|
+
totalChars() {
|
|
19291
|
+
return totalChars;
|
|
19292
|
+
},
|
|
19293
|
+
totalLines() {
|
|
19294
|
+
return totalChars > 0 ? totalNewlines + 1 : 0;
|
|
19295
|
+
}
|
|
19296
|
+
};
|
|
19297
|
+
}
|
|
18887
19298
|
async function launchProcessTool(args2) {
|
|
18888
19299
|
const parsed = parseWorkspaceToolArguments(args2.call.arguments);
|
|
18889
19300
|
const command = requireShellCommand(parsed, args2.call.name);
|
|
@@ -18911,6 +19322,14 @@ async function launchProcessTool(args2) {
|
|
|
18911
19322
|
stdio: ["ignore", "pipe", "pipe"],
|
|
18912
19323
|
detached
|
|
18913
19324
|
});
|
|
19325
|
+
const stdoutCapture = createLaunchProcessStreamCapture();
|
|
19326
|
+
const stderrCapture = createLaunchProcessStreamCapture();
|
|
19327
|
+
proc.stdout?.on("data", (chunk) => stdoutCapture.push(chunk));
|
|
19328
|
+
proc.stderr?.on("data", (chunk) => stderrCapture.push(chunk));
|
|
19329
|
+
proc.stdout?.on("error", () => {
|
|
19330
|
+
});
|
|
19331
|
+
proc.stderr?.on("error", () => {
|
|
19332
|
+
});
|
|
18914
19333
|
const pid = proc.pid;
|
|
18915
19334
|
if (typeof pid !== "number") {
|
|
18916
19335
|
return {
|
|
@@ -18951,7 +19370,38 @@ async function launchProcessTool(args2) {
|
|
|
18951
19370
|
process.removeListener("SIGTERM", cleanupChildOnHostSignal);
|
|
18952
19371
|
process.removeListener("SIGINT", cleanupChildOnHostSignal);
|
|
18953
19372
|
}
|
|
18954
|
-
|
|
19373
|
+
const exitCode = code ?? 1;
|
|
19374
|
+
let capsule;
|
|
19375
|
+
try {
|
|
19376
|
+
capsule = buildProcessTaskResultCapsule({
|
|
19377
|
+
// The full captured output (bounded prefix when the process was
|
|
19378
|
+
// extremely chatty): the module tails it for the inline capsule and
|
|
19379
|
+
// spills it for recovery. Provenance carries the live original-stream
|
|
19380
|
+
// counters so truncated/spill metadata never derives from the ring.
|
|
19381
|
+
stdout: stdoutCapture.text(),
|
|
19382
|
+
stderr: stderrCapture.text(),
|
|
19383
|
+
stdoutTail: stdoutCapture.tailText(),
|
|
19384
|
+
stderrTail: stderrCapture.tailText(),
|
|
19385
|
+
exitCode,
|
|
19386
|
+
// Duration measured from the registry envelope's startedAt (spawn).
|
|
19387
|
+
startedAt: envelope.startedAt,
|
|
19388
|
+
workspaceRoot: args2.workspaceRoot,
|
|
19389
|
+
streamProvenance: {
|
|
19390
|
+
stdout: {
|
|
19391
|
+
evicted: stdoutCapture.evicted(),
|
|
19392
|
+
totalChars: stdoutCapture.totalChars(),
|
|
19393
|
+
totalLines: stdoutCapture.totalLines()
|
|
19394
|
+
},
|
|
19395
|
+
stderr: {
|
|
19396
|
+
evicted: stderrCapture.evicted(),
|
|
19397
|
+
totalChars: stderrCapture.totalChars(),
|
|
19398
|
+
totalLines: stderrCapture.totalLines()
|
|
19399
|
+
}
|
|
19400
|
+
}
|
|
19401
|
+
});
|
|
19402
|
+
} catch {
|
|
19403
|
+
}
|
|
19404
|
+
registry2.markExited(pid, exitCode, capsule);
|
|
18955
19405
|
});
|
|
18956
19406
|
const activity = extractActivity(parsed);
|
|
18957
19407
|
const resultData = { pid, label, taskId: envelope.taskId, status: "running" };
|
|
@@ -18963,6 +19413,13 @@ async function launchProcessTool(args2) {
|
|
|
18963
19413
|
label,
|
|
18964
19414
|
status: "running",
|
|
18965
19415
|
taskId: envelope.taskId,
|
|
19416
|
+
// P0 machine-readable execution state (consistent with the real wake
|
|
19417
|
+
// contract): a real background task from birth, but ambient — its
|
|
19418
|
+
// terminal result rides the next real turn's notice, not an automatic
|
|
19419
|
+
// completion turn.
|
|
19420
|
+
executionState: "background",
|
|
19421
|
+
trackedBackgroundTask: true,
|
|
19422
|
+
completionNotification: "next-turn-notice",
|
|
18966
19423
|
processLaunch: resultData,
|
|
18967
19424
|
...activity ? { activity } : {}
|
|
18968
19425
|
}
|
|
@@ -19065,7 +19522,7 @@ async function tasksTool(_args) {
|
|
|
19065
19522
|
}
|
|
19066
19523
|
async function openDesktopPreviewTool(args2) {
|
|
19067
19524
|
const parsed = parseWorkspaceToolArguments(args2.call.arguments);
|
|
19068
|
-
const url =
|
|
19525
|
+
const url = asTrimmedString(parsed.url);
|
|
19069
19526
|
if (!url) {
|
|
19070
19527
|
return {
|
|
19071
19528
|
content: JSON.stringify({ error: "openDesktopPreview requires a non-empty url." }),
|
|
@@ -19397,7 +19854,9 @@ function resolveLocalToolPolicy(args2) {
|
|
|
19397
19854
|
reason: `${toolName} is blocked by the local runtime safety policy.`
|
|
19398
19855
|
};
|
|
19399
19856
|
}
|
|
19400
|
-
const allowedByEnv = new Set(
|
|
19857
|
+
const allowedByEnv = new Set(
|
|
19858
|
+
parseToolAllowlist(args2.env.NOLO_LOCAL_ALLOWED_TOOLS).map(normalizeLocalToolName)
|
|
19859
|
+
);
|
|
19401
19860
|
const agentTools = new Set(
|
|
19402
19861
|
(args2.agentToolNames ?? []).flatMap((item) => {
|
|
19403
19862
|
const normalized = normalizeLocalToolName(item);
|
|
@@ -19420,7 +19879,7 @@ function resolveLocalToolPolicy(args2) {
|
|
|
19420
19879
|
};
|
|
19421
19880
|
}
|
|
19422
19881
|
async function executeLocalToolWithPolicy(args2) {
|
|
19423
|
-
if (args2.runToolNames !== void 0 && !args2.runToolNames.includes(normalizeLocalToolName(args2.call.name))) {
|
|
19882
|
+
if (args2.runToolNames !== void 0 && !args2.runToolNames.map(normalizeLocalToolName).includes(normalizeLocalToolName(args2.call.name))) {
|
|
19424
19883
|
throw new Error(`${args2.call.name} is outside the final run tool surface.`);
|
|
19425
19884
|
}
|
|
19426
19885
|
const decision = resolveLocalToolPolicy({
|
|
@@ -19607,10 +20066,10 @@ function buildLoadSkillExecutor(args2) {
|
|
|
19607
20066
|
metadata: { loadSkill: true, resolved: false }
|
|
19608
20067
|
};
|
|
19609
20068
|
}
|
|
19610
|
-
const { resolveSkillByName } = await import("./skillDiscovery-
|
|
20069
|
+
const { resolveSkillByName } = await import("./skillDiscovery-ZBU76COE.js");
|
|
19611
20070
|
const resolved = resolveSkillByName(args2.cwd, name);
|
|
19612
20071
|
if (!resolved) {
|
|
19613
|
-
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-
|
|
20072
|
+
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-SBBWTANC.js");
|
|
19614
20073
|
const builtin = resolveBuiltinSkillByName(name);
|
|
19615
20074
|
if (builtin) {
|
|
19616
20075
|
return {
|
|
@@ -19653,7 +20112,7 @@ ${body}`,
|
|
|
19653
20112
|
};
|
|
19654
20113
|
}
|
|
19655
20114
|
async function formatUnknownSkillMessage(cwd, requestedName) {
|
|
19656
|
-
const { discoverSkills } = await import("./skillDiscovery-
|
|
20115
|
+
const { discoverSkills } = await import("./skillDiscovery-ZBU76COE.js");
|
|
19657
20116
|
let available = [];
|
|
19658
20117
|
try {
|
|
19659
20118
|
available = discoverSkills(cwd).map((s) => s.name);
|
|
@@ -19668,739 +20127,29 @@ No skills were discovered in this workspace.`;
|
|
|
19668
20127
|
Available skills: ${available.join(", ")}`;
|
|
19669
20128
|
}
|
|
19670
20129
|
|
|
19671
|
-
// packages/
|
|
19672
|
-
|
|
19673
|
-
|
|
19674
|
-
|
|
19675
|
-
|
|
19676
|
-
|
|
19677
|
-
|
|
19678
|
-
|
|
19679
|
-
|
|
19680
|
-
|
|
19681
|
-
|
|
19682
|
-
|
|
19683
|
-
|
|
19684
|
-
|
|
19685
|
-
|
|
19686
|
-
|
|
19687
|
-
|
|
19688
|
-
// packages/agent-runtime/antigravityCloudCodeProvider.ts
|
|
19689
|
-
import { randomUUID } from "node:crypto";
|
|
19690
|
-
|
|
19691
|
-
// packages/agent-runtime/antigravityWireModel.ts
|
|
19692
|
-
var WIRE_PROFILES = {
|
|
19693
|
-
// Antigravity discovery exposes 3.7 Flash as one tiered wire model.
|
|
19694
|
-
// The UI labels its effort variants (Low/Medium/High), but the literal
|
|
19695
|
-
// -medium/-high ids return 404 from streamGenerateContent.
|
|
19696
|
-
"gemini-3.7-flash-tiered": { modelEnum: "MODEL_PLACEHOLDER_M301", maxOutputTokens: 65536 },
|
|
19697
|
-
// Gemini 3.8 Flash 沿用 3.7 的 tiered 兼容策略:仓库内暂无 Antigravity discovery
|
|
19698
|
-
// 证据确认 3.8 的 wire modelEnum,禁止虚构,先只声明同档输出上限;enum 待
|
|
19699
|
-
// discovery 证据到位后补齐。
|
|
19700
|
-
"gemini-3.8-flash-tiered": { maxOutputTokens: 65536 },
|
|
19701
|
-
"gemini-3.6-flash-low": { maxOutputTokens: 65536 },
|
|
19702
|
-
"gemini-3.6-flash-medium": { maxOutputTokens: 65536 },
|
|
19703
|
-
"gemini-3.6-flash-high": { maxOutputTokens: 65536 },
|
|
19704
|
-
// 旧模型 wire 映射保留:存量自定义 agent 仍可能引用(注册表已下线不影响此处)。
|
|
19705
|
-
"gemini-3.5-flash-extra-low": { modelEnum: "MODEL_PLACEHOLDER_M187", maxOutputTokens: 65536 },
|
|
19706
|
-
"gemini-3.5-flash-low": { modelEnum: "MODEL_PLACEHOLDER_M20", maxOutputTokens: 65536 },
|
|
19707
|
-
"gemini-3-flash-agent": { modelEnum: "MODEL_PLACEHOLDER_M132", maxOutputTokens: 65536 },
|
|
19708
|
-
"gemini-3.1-pro-low": { modelEnum: "MODEL_PLACEHOLDER_M36", maxOutputTokens: 65535 },
|
|
19709
|
-
"gemini-pro-agent": { modelEnum: "MODEL_PLACEHOLDER_M16", maxOutputTokens: 65535 },
|
|
19710
|
-
"claude-sonnet-5": { maxOutputTokens: 64e3 },
|
|
19711
|
-
"claude-sonnet-4-6": { maxOutputTokens: 64e3 },
|
|
19712
|
-
"claude-opus-4-6-thinking": { maxOutputTokens: 64e3 },
|
|
19713
|
-
"gemini-2.5-flash": { maxOutputTokens: 65536 },
|
|
19714
|
-
"gemini-2.5-pro": { maxOutputTokens: 65536 }
|
|
19715
|
-
};
|
|
19716
|
-
function resolveAntigravityWireModel(logicalModelId) {
|
|
19717
|
-
const id = logicalModelId.trim();
|
|
19718
|
-
const lower = id.toLowerCase();
|
|
19719
|
-
if (lower === "gemini-3.5-flash") {
|
|
19720
|
-
const wireModelId = "gemini-3.5-flash-low";
|
|
19721
|
-
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
19722
|
-
}
|
|
19723
|
-
if (lower === "gemini-3.7-flash" || ["gemini-3.7-flash-low", "gemini-3.7-flash-medium", "gemini-3.7-flash-high"].includes(lower)) {
|
|
19724
|
-
const wireModelId = "gemini-3.7-flash-tiered";
|
|
19725
|
-
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
19726
|
-
}
|
|
19727
|
-
if (lower === "gemini-3.8-flash" || ["gemini-3.8-flash-low", "gemini-3.8-flash-medium", "gemini-3.8-flash-high"].includes(lower)) {
|
|
19728
|
-
const wireModelId = "gemini-3.8-flash-tiered";
|
|
19729
|
-
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
19730
|
-
}
|
|
19731
|
-
if (lower === "gemini-3.6-flash") {
|
|
19732
|
-
const wireModelId = "gemini-3.6-flash-low";
|
|
19733
|
-
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
19734
|
-
}
|
|
19735
|
-
if (lower === "gemini-3.1-pro" || lower === "gemini-3.1-pro-preview") {
|
|
19736
|
-
const wireModelId = "gemini-3.1-pro-low";
|
|
19737
|
-
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
19738
|
-
}
|
|
19739
|
-
if (WIRE_PROFILES[id]) {
|
|
19740
|
-
return { wireModelId: id, profile: WIRE_PROFILES[id] };
|
|
19741
|
-
}
|
|
19742
|
-
return { wireModelId: id };
|
|
19743
|
-
}
|
|
19744
|
-
|
|
19745
|
-
// packages/agent-runtime/geminiNativeShared.ts
|
|
19746
|
-
var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
19747
|
-
function resolveGeminiModelQuirks(modelId) {
|
|
19748
|
-
const lower = modelId.toLowerCase();
|
|
19749
|
-
const isGemini3 = lower.includes("gemini-3");
|
|
19750
|
-
const isStrictSignatureModel = lower.includes("gemini-3.5") || lower.includes("flash-preview");
|
|
19751
|
-
const isClaude = lower.includes("claude");
|
|
19752
|
-
return {
|
|
19753
|
-
requiresThoughtSignature: isGemini3,
|
|
19754
|
-
allowsThoughtSignatureSentinel: isGemini3 && !isStrictSignatureModel,
|
|
19755
|
-
isClaudeCrossModel: isClaude
|
|
19756
|
-
};
|
|
19757
|
-
}
|
|
19758
|
-
function isGemini3Model(modelId) {
|
|
19759
|
-
return resolveGeminiModelQuirks(modelId).requiresThoughtSignature;
|
|
19760
|
-
}
|
|
19761
|
-
function messageText(content) {
|
|
19762
|
-
if (typeof content === "string") return content;
|
|
19763
|
-
if (!Array.isArray(content)) return "";
|
|
19764
|
-
return content.filter(
|
|
19765
|
-
(part) => part?.type === "text"
|
|
19766
|
-
).map((part) => part.text).join("\n").trim();
|
|
19767
|
-
}
|
|
19768
|
-
function parseDataUrlToInlineData(url) {
|
|
19769
|
-
const match7 = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
|
|
19770
|
-
url
|
|
19771
|
-
);
|
|
19772
|
-
if (!match7) return null;
|
|
19773
|
-
return { mimeType: match7[1], data: match7[2] };
|
|
19774
|
-
}
|
|
19775
|
-
function extractInlineDataParts(content) {
|
|
19776
|
-
if (!Array.isArray(content)) return [];
|
|
19777
|
-
const parts2 = [];
|
|
19778
|
-
for (const part of content) {
|
|
19779
|
-
if (!part || typeof part !== "object") continue;
|
|
19780
|
-
if (part.type !== "image_url") continue;
|
|
19781
|
-
const url = part.image_url?.url;
|
|
19782
|
-
if (typeof url !== "string" || !url.trim()) continue;
|
|
19783
|
-
const inline = parseDataUrlToInlineData(url);
|
|
19784
|
-
if (inline) parts2.push({ inlineData: inline });
|
|
19785
|
-
}
|
|
19786
|
-
return parts2;
|
|
19787
|
-
}
|
|
19788
|
-
function convertOpenAiMessagesToGemini(messages, options) {
|
|
19789
|
-
const contents = [];
|
|
19790
|
-
const systemTexts = [];
|
|
19791
|
-
let toolCallIndex = 0;
|
|
19792
|
-
let pendingFunctionCalls = [];
|
|
19793
|
-
const pushOrMergeContent = (role, parts2) => {
|
|
19794
|
-
if (parts2.length === 0) return;
|
|
19795
|
-
const last = contents[contents.length - 1];
|
|
19796
|
-
if (last && last.role === role) {
|
|
19797
|
-
last.parts.push(...parts2);
|
|
19798
|
-
} else {
|
|
19799
|
-
contents.push({ role, parts: parts2 });
|
|
19800
|
-
}
|
|
19801
|
-
};
|
|
19802
|
-
const flushPendingFunctionCalls = () => {
|
|
19803
|
-
if (pendingFunctionCalls.length === 0) return;
|
|
19804
|
-
const dummyResponses = pendingFunctionCalls.map(
|
|
19805
|
-
({ name, id }) => ({
|
|
19806
|
-
functionResponse: {
|
|
19807
|
-
name,
|
|
19808
|
-
response: { output: "{}" },
|
|
19809
|
-
...id ? { id } : {}
|
|
19810
|
-
}
|
|
19811
|
-
})
|
|
19812
|
-
);
|
|
19813
|
-
pendingFunctionCalls = [];
|
|
19814
|
-
pushOrMergeContent("user", dummyResponses);
|
|
19815
|
-
};
|
|
19816
|
-
for (const raw of messages) {
|
|
19817
|
-
if (!raw || typeof raw !== "object" || !("role" in raw)) continue;
|
|
19818
|
-
const role = String(raw.role);
|
|
19819
|
-
const content = "content" in raw ? raw.content : null;
|
|
19820
|
-
if (role === "system") {
|
|
19821
|
-
const text = messageText(
|
|
19822
|
-
content
|
|
19823
|
-
);
|
|
19824
|
-
if (text) systemTexts.push(text);
|
|
19825
|
-
continue;
|
|
19826
|
-
}
|
|
19827
|
-
if (role === "user") {
|
|
19828
|
-
flushPendingFunctionCalls();
|
|
19829
|
-
const text = messageText(
|
|
19830
|
-
content
|
|
19831
|
-
);
|
|
19832
|
-
const imageParts = extractInlineDataParts(
|
|
19833
|
-
content
|
|
19834
|
-
);
|
|
19835
|
-
if (!text && imageParts.length === 0) continue;
|
|
19836
|
-
const parts2 = [];
|
|
19837
|
-
if (text) parts2.push({ text });
|
|
19838
|
-
for (const img of imageParts) parts2.push(img);
|
|
19839
|
-
pushOrMergeContent("user", parts2);
|
|
19840
|
-
continue;
|
|
19841
|
-
}
|
|
19842
|
-
if (role === "assistant") {
|
|
19843
|
-
flushPendingFunctionCalls();
|
|
19844
|
-
const text = messageText(
|
|
19845
|
-
content
|
|
19846
|
-
);
|
|
19847
|
-
const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
|
|
19848
|
-
const parts2 = [];
|
|
19849
|
-
if (text) {
|
|
19850
|
-
parts2.push({ text });
|
|
19851
|
-
}
|
|
19852
|
-
for (const call of toolCalls) {
|
|
19853
|
-
const name = call?.function?.name?.trim();
|
|
19854
|
-
if (!name) continue;
|
|
19855
|
-
const id = call.id?.trim() || `${name}_${toolCallIndex++}`;
|
|
19856
|
-
pendingFunctionCalls.push({ name, id });
|
|
19857
|
-
const realSignature = typeof call.thought_signature === "string" && call.thought_signature ? call.thought_signature : void 0;
|
|
19858
|
-
const isFirstFunctionCallPart = !parts2.some(
|
|
19859
|
-
(p) => "functionCall" in p
|
|
19860
|
-
);
|
|
19861
|
-
const signature = realSignature ?? (options.attachSkipThoughtSignature && isFirstFunctionCallPart ? SKIP_THOUGHT_SIGNATURE : void 0);
|
|
19862
|
-
const part = {
|
|
19863
|
-
functionCall: {
|
|
19864
|
-
name,
|
|
19865
|
-
args: parseToolArgs(call.function?.arguments),
|
|
19866
|
-
...id ? { id } : {}
|
|
19867
|
-
},
|
|
19868
|
-
...signature ? { thoughtSignature: signature } : {}
|
|
19869
|
-
};
|
|
19870
|
-
parts2.push(part);
|
|
19871
|
-
}
|
|
19872
|
-
pushOrMergeContent("model", parts2);
|
|
19873
|
-
continue;
|
|
19874
|
-
}
|
|
19875
|
-
if (role === "tool") {
|
|
19876
|
-
const toolCallId = "tool_call_id" in raw && typeof raw.tool_call_id === "string" ? raw.tool_call_id : "";
|
|
19877
|
-
const rawName = "name" in raw && typeof raw.name === "string" ? raw.name.trim() : "";
|
|
19878
|
-
const pendingIndex = pendingFunctionCalls.findIndex(
|
|
19879
|
-
(p) => toolCallId ? p.id === toolCallId : rawName ? p.name === rawName : true
|
|
19880
|
-
);
|
|
19881
|
-
if (pendingIndex === -1) continue;
|
|
19882
|
-
const [{ name, id }] = pendingFunctionCalls.splice(pendingIndex, 1);
|
|
19883
|
-
const output = messageText(content) || "{}";
|
|
19884
|
-
pushOrMergeContent("user", [
|
|
19885
|
-
{
|
|
19886
|
-
functionResponse: {
|
|
19887
|
-
name,
|
|
19888
|
-
response: { output },
|
|
19889
|
-
// 保留 OpenAI tool_call_id:antigravity Cloud Code Assist 网关把
|
|
19890
|
-
// Gemini contents 转成 Claude messages 时需要 functionResponse →
|
|
19891
|
-
// tool_result 的 tool_use_id;缺 id 时网关报
|
|
19892
|
-
// "tool_result.tool_use_id: Field required"(HTTP 400)。
|
|
19893
|
-
...id ? { id } : {}
|
|
19894
|
-
}
|
|
19895
|
-
}
|
|
19896
|
-
]);
|
|
19897
|
-
}
|
|
19898
|
-
}
|
|
19899
|
-
flushPendingFunctionCalls();
|
|
19900
|
-
if (contents.length > 0 && contents[0]?.role === "model") {
|
|
19901
|
-
contents.unshift({
|
|
19902
|
-
role: "user",
|
|
19903
|
-
parts: [{ text: "Continue the conversation." }]
|
|
19904
|
-
});
|
|
19905
|
-
}
|
|
19906
|
-
return { contents, systemTexts };
|
|
19907
|
-
}
|
|
19908
|
-
function parseToolArgs(raw) {
|
|
19909
|
-
if (typeof raw === "string") {
|
|
19910
|
-
try {
|
|
19911
|
-
const parsed = JSON.parse(raw);
|
|
19912
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
19913
|
-
return parsed;
|
|
19914
|
-
}
|
|
19915
|
-
} catch {
|
|
19916
|
-
}
|
|
19917
|
-
}
|
|
19918
|
-
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
19919
|
-
return raw;
|
|
19920
|
-
}
|
|
19921
|
-
return {};
|
|
19922
|
-
}
|
|
19923
|
-
function sanitizeGeminiSchemaNode(node, active) {
|
|
19924
|
-
const out = {};
|
|
19925
|
-
if (!node || typeof node !== "object" || Array.isArray(node)) {
|
|
19926
|
-
return { type: "string" };
|
|
19927
|
-
}
|
|
19928
|
-
if (active?.has(node)) {
|
|
19929
|
-
return { type: "object", description: "(circular schema reference)" };
|
|
19930
|
-
}
|
|
19931
|
-
const seen = active ?? /* @__PURE__ */ new WeakSet();
|
|
19932
|
-
seen.add(node);
|
|
19933
|
-
try {
|
|
19934
|
-
return sanitizeGeminiSchemaNodeInner(node, out, seen);
|
|
19935
|
-
} finally {
|
|
19936
|
-
seen.delete(node);
|
|
19937
|
-
}
|
|
19938
|
-
}
|
|
19939
|
-
function sanitizeGeminiSchemaNodeInner(src, out, seen) {
|
|
19940
|
-
if (Array.isArray(src.type)) {
|
|
19941
|
-
const firstNonNull = src.type.find((t) => t !== "null");
|
|
19942
|
-
if (typeof firstNonNull === "string") out.type = firstNonNull;
|
|
19943
|
-
out.nullable = true;
|
|
19944
|
-
} else if (typeof src.type === "string") {
|
|
19945
|
-
out.type = src.type;
|
|
19946
|
-
}
|
|
19947
|
-
if (typeof src.description === "string") out.description = src.description;
|
|
19948
|
-
if (typeof src.minimum === "number") out.minimum = src.minimum;
|
|
19949
|
-
if (typeof src.maximum === "number") out.maximum = src.maximum;
|
|
19950
|
-
if (Array.isArray(src.enum) && src.enum.length > 0) out.enum = src.enum;
|
|
19951
|
-
if (src.nullable === true) out.nullable = true;
|
|
19952
|
-
if ("const" in src && src.const !== void 0 && !out.enum) {
|
|
19953
|
-
out.enum = [src.const];
|
|
19954
|
-
}
|
|
19955
|
-
const variantBranches = [
|
|
19956
|
-
...Array.isArray(src.oneOf) ? src.oneOf : [],
|
|
19957
|
-
...Array.isArray(src.anyOf) ? src.anyOf : []
|
|
19958
|
-
];
|
|
19959
|
-
if (variantBranches.length > 0) {
|
|
19960
|
-
const mergedProperties = {};
|
|
19961
|
-
let requiredIntersection;
|
|
19962
|
-
for (const branch of variantBranches) {
|
|
19963
|
-
const sanitized = sanitizeGeminiSchemaNode(branch, seen);
|
|
19964
|
-
const branchProperties = sanitized.properties ?? {};
|
|
19965
|
-
for (const [key, value] of Object.entries(branchProperties)) {
|
|
19966
|
-
const previous = mergedProperties[key];
|
|
19967
|
-
const prevEnum = previous?.enum;
|
|
19968
|
-
const nextEnum = value?.enum;
|
|
19969
|
-
if (prevEnum && nextEnum) {
|
|
19970
|
-
mergedProperties[key] = {
|
|
19971
|
-
...value,
|
|
19972
|
-
enum: [.../* @__PURE__ */ new Set([...prevEnum, ...nextEnum])]
|
|
19973
|
-
};
|
|
19974
|
-
} else {
|
|
19975
|
-
mergedProperties[key] = value;
|
|
19976
|
-
}
|
|
19977
|
-
}
|
|
19978
|
-
const branchRequired = Array.isArray(sanitized.required) ? sanitized.required : [];
|
|
19979
|
-
requiredIntersection = requiredIntersection === void 0 ? [...branchRequired] : requiredIntersection.filter((r) => branchRequired.includes(r));
|
|
19980
|
-
}
|
|
19981
|
-
out.properties = {
|
|
19982
|
-
...out.properties ?? {},
|
|
19983
|
-
...mergedProperties
|
|
19984
|
-
};
|
|
19985
|
-
if (requiredIntersection !== void 0 && requiredIntersection.length > 0) {
|
|
19986
|
-
out.required = requiredIntersection;
|
|
19987
|
-
}
|
|
19988
|
-
if (typeof out.type !== "string") out.type = "object";
|
|
19989
|
-
}
|
|
19990
|
-
if (Array.isArray(src.allOf)) {
|
|
19991
|
-
for (const branch of src.allOf) {
|
|
19992
|
-
const sanitized = sanitizeGeminiSchemaNode(branch, seen);
|
|
19993
|
-
out.properties = {
|
|
19994
|
-
...out.properties ?? {},
|
|
19995
|
-
...sanitized.properties ?? {}
|
|
19996
|
-
};
|
|
19997
|
-
if (Array.isArray(sanitized.required)) {
|
|
19998
|
-
out.required = [
|
|
19999
|
-
.../* @__PURE__ */ new Set([
|
|
20000
|
-
...out.required ?? [],
|
|
20001
|
-
...sanitized.required ?? []
|
|
20002
|
-
])
|
|
20003
|
-
];
|
|
20004
|
-
}
|
|
20005
|
-
}
|
|
20006
|
-
if (typeof out.type !== "string") out.type = "object";
|
|
20007
|
-
}
|
|
20008
|
-
if (src.properties && typeof src.properties === "object") {
|
|
20009
|
-
const properties = {};
|
|
20010
|
-
for (const [key, value] of Object.entries(
|
|
20011
|
-
src.properties
|
|
20012
|
-
)) {
|
|
20013
|
-
properties[key] = sanitizeGeminiSchemaNode(value, seen);
|
|
20014
|
-
}
|
|
20015
|
-
out.properties = properties;
|
|
20016
|
-
if (typeof out.type !== "string") out.type = "object";
|
|
20017
|
-
}
|
|
20018
|
-
if (Array.isArray(src.required)) {
|
|
20019
|
-
const properties = out.properties ?? {};
|
|
20020
|
-
const required = [...new Set(src.required)].filter(
|
|
20021
|
-
(r) => typeof r === "string" && r in properties
|
|
20022
|
-
);
|
|
20023
|
-
if (required.length > 0) out.required = required;
|
|
20024
|
-
}
|
|
20025
|
-
if (src.items !== void 0) {
|
|
20026
|
-
out.items = sanitizeGeminiSchemaNode(src.items, seen);
|
|
20027
|
-
if (typeof out.type !== "string") out.type = "array";
|
|
20028
|
-
}
|
|
20029
|
-
if (typeof out.type !== "string") out.type = "object";
|
|
20030
|
-
return out;
|
|
20031
|
-
}
|
|
20032
|
-
function convertOpenAiToolsToGemini(tools) {
|
|
20033
|
-
if (!Array.isArray(tools) || tools.length === 0) return void 0;
|
|
20034
|
-
const declarations = [];
|
|
20035
|
-
for (const tool of tools) {
|
|
20036
|
-
if (!tool || typeof tool !== "object" || !("function" in tool)) continue;
|
|
20037
|
-
const fn3 = tool.function;
|
|
20038
|
-
const name = typeof fn3.name === "string" ? fn3.name : "";
|
|
20039
|
-
if (!name) continue;
|
|
20040
|
-
declarations.push({
|
|
20041
|
-
name,
|
|
20042
|
-
description: typeof fn3.description === "string" ? fn3.description : "",
|
|
20043
|
-
parameters: sanitizeGeminiSchemaNode(
|
|
20044
|
-
fn3.parameters ?? { type: "object", properties: {} }
|
|
20045
|
-
)
|
|
20046
|
-
});
|
|
20047
|
-
}
|
|
20048
|
-
if (declarations.length === 0) return void 0;
|
|
20049
|
-
return [{ functionDeclarations: declarations }];
|
|
20050
|
-
}
|
|
20051
|
-
function createGeminiAccumulatorState() {
|
|
20052
|
-
return {
|
|
20053
|
-
text: "",
|
|
20054
|
-
toolCalls: [],
|
|
20055
|
-
reasoning: "",
|
|
20056
|
-
events: []
|
|
20057
|
-
};
|
|
20058
|
-
}
|
|
20059
|
-
function applyGeminiChunk(chunk, state, options) {
|
|
20060
|
-
if (!chunk || typeof chunk !== "object") return;
|
|
20061
|
-
const response = "response" in chunk && chunk.response && typeof chunk.response === "object" ? chunk.response : chunk;
|
|
20062
|
-
if ("usageMetadata" in response && response.usageMetadata && typeof response.usageMetadata === "object") {
|
|
20063
|
-
const meta = response.usageMetadata;
|
|
20064
|
-
const prompt = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : 0;
|
|
20065
|
-
const candidates2 = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : 0;
|
|
20066
|
-
const total = typeof meta.totalTokenCount === "number" ? meta.totalTokenCount : prompt + candidates2;
|
|
20067
|
-
const cached3 = typeof meta.cachedContentTokenCount === "number" && Number.isFinite(meta.cachedContentTokenCount) ? (
|
|
20068
|
-
// cached ⊆ prompt;对畸形上游防御性钳位,避免 cache_read > input 破坏归一化与计费
|
|
20069
|
-
Math.min(Math.max(0, Math.floor(meta.cachedContentTokenCount)), prompt)
|
|
20070
|
-
) : 0;
|
|
20071
|
-
state.usage = {
|
|
20072
|
-
prompt_tokens: prompt,
|
|
20073
|
-
completion_tokens: candidates2,
|
|
20074
|
-
total_tokens: total,
|
|
20075
|
-
...cached3 > 0 ? { cache_read_input_tokens: cached3 } : {}
|
|
20076
|
-
};
|
|
20077
|
-
state.events.push({ kind: "usage", usage: state.usage });
|
|
20078
|
-
}
|
|
20079
|
-
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
|
|
20080
|
-
for (const candidate of candidates) {
|
|
20081
|
-
if (!candidate || typeof candidate !== "object") continue;
|
|
20082
|
-
const candidateFinishReason = candidate.finishReason;
|
|
20083
|
-
if (typeof candidateFinishReason === "string" && candidateFinishReason.trim()) {
|
|
20084
|
-
state.finishReason = candidateFinishReason.trim();
|
|
20085
|
-
state.events.push({ kind: "finish", reason: state.finishReason });
|
|
20086
|
-
}
|
|
20087
|
-
const parts2 = Array.isArray(
|
|
20088
|
-
candidate.content?.parts
|
|
20089
|
-
) ? candidate.content.parts : [];
|
|
20090
|
-
for (const part of parts2) {
|
|
20091
|
-
if (!part || typeof part !== "object") continue;
|
|
20092
|
-
const partSignature = part.thoughtSignature;
|
|
20093
|
-
const isThought = Boolean(part.thought);
|
|
20094
|
-
if ("text" in part && typeof part.text === "string") {
|
|
20095
|
-
const piece = part.text;
|
|
20096
|
-
if (!isThought) {
|
|
20097
|
-
state.text += piece;
|
|
20098
|
-
if (piece) {
|
|
20099
|
-
state.events.push({ kind: "text", text: piece });
|
|
20100
|
-
if (options?.onTextDelta) options.onTextDelta(piece);
|
|
20101
|
-
}
|
|
20102
|
-
} else {
|
|
20103
|
-
state.reasoning += piece;
|
|
20104
|
-
if (piece) {
|
|
20105
|
-
state.events.push({ kind: "reasoning", text: piece });
|
|
20106
|
-
if (options?.onReasoningDelta) options.onReasoningDelta(piece);
|
|
20107
|
-
}
|
|
20108
|
-
}
|
|
20109
|
-
}
|
|
20110
|
-
if (isThought && typeof partSignature === "string" && partSignature) {
|
|
20111
|
-
state.pendingThoughtSignature = partSignature;
|
|
20112
|
-
}
|
|
20113
|
-
if ("functionCall" in part && part.functionCall) {
|
|
20114
|
-
const call = part.functionCall;
|
|
20115
|
-
const name = typeof call.name === "string" ? call.name : "tool";
|
|
20116
|
-
const id = typeof call.id === "string" ? call.id : `${name}_${state.toolCalls.length}`;
|
|
20117
|
-
const argsObj = call.args && typeof call.args === "object" ? call.args : {};
|
|
20118
|
-
const resolvedSignature = typeof partSignature === "string" && partSignature ? partSignature : state.pendingThoughtSignature;
|
|
20119
|
-
state.pendingThoughtSignature = void 0;
|
|
20120
|
-
const toolCall = {
|
|
20121
|
-
id,
|
|
20122
|
-
type: "function",
|
|
20123
|
-
function: { name, arguments: JSON.stringify(argsObj) },
|
|
20124
|
-
...typeof resolvedSignature === "string" && resolvedSignature ? { thought_signature: resolvedSignature } : {}
|
|
20125
|
-
};
|
|
20126
|
-
state.toolCalls.push(toolCall);
|
|
20127
|
-
state.events.push({ kind: "tool_call", toolCall });
|
|
20128
|
-
}
|
|
20129
|
-
}
|
|
20130
|
-
}
|
|
20131
|
-
}
|
|
20132
|
-
function accumulateGeminiChunks(chunks2, options) {
|
|
20133
|
-
const state = createGeminiAccumulatorState();
|
|
20134
|
-
for (const chunk of chunks2) {
|
|
20135
|
-
applyGeminiChunk(chunk, state, options);
|
|
20136
|
-
}
|
|
20137
|
-
return {
|
|
20138
|
-
text: state.text,
|
|
20139
|
-
toolCalls: state.toolCalls,
|
|
20140
|
-
usage: state.usage,
|
|
20141
|
-
finishReason: state.finishReason,
|
|
20142
|
-
reasoningContent: state.reasoning,
|
|
20143
|
-
events: state.events
|
|
20144
|
-
};
|
|
20145
|
-
}
|
|
20146
|
-
async function accumulateGeminiStream(stream, options) {
|
|
20147
|
-
const state = createGeminiAccumulatorState();
|
|
20148
|
-
for await (const chunk of stream) {
|
|
20149
|
-
applyGeminiChunk(chunk, state, options);
|
|
20150
|
-
}
|
|
20151
|
-
return {
|
|
20152
|
-
text: state.text,
|
|
20153
|
-
toolCalls: state.toolCalls,
|
|
20154
|
-
usage: state.usage,
|
|
20155
|
-
finishReason: state.finishReason,
|
|
20156
|
-
reasoningContent: state.reasoning,
|
|
20157
|
-
events: state.events
|
|
20158
|
-
};
|
|
20159
|
-
}
|
|
20160
|
-
function shouldUseGeminiNativeToolRoute(provider, model, tools, isImageModel) {
|
|
20161
|
-
return provider === "google" && !isImageModel(model) && isGemini3Model(model) && Array.isArray(tools) && tools.length > 0;
|
|
20162
|
-
}
|
|
20163
|
-
function buildGeminiGenerateContentRequest(args2) {
|
|
20164
|
-
const { contents, systemTexts } = convertOpenAiMessagesToGemini(
|
|
20165
|
-
args2.messages,
|
|
20166
|
-
{ attachSkipThoughtSignature: args2.attachSkipThoughtSignature }
|
|
20167
|
-
);
|
|
20168
|
-
const request3 = { contents };
|
|
20169
|
-
if (systemTexts.length > 0) {
|
|
20170
|
-
request3.systemInstruction = {
|
|
20171
|
-
role: "user",
|
|
20172
|
-
parts: systemTexts.map((text) => ({ text }))
|
|
20173
|
-
};
|
|
20174
|
-
}
|
|
20175
|
-
const toolsResult = convertOpenAiToolsToGemini(args2.tools);
|
|
20176
|
-
if (toolsResult) {
|
|
20177
|
-
request3.tools = toolsResult;
|
|
20178
|
-
request3.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
|
|
20179
|
-
}
|
|
20180
|
-
const generationConfig = {};
|
|
20181
|
-
if (typeof args2.maxTokens === "number" && args2.maxTokens > 0) {
|
|
20182
|
-
generationConfig.maxOutputTokens = args2.maxTokens;
|
|
20183
|
-
}
|
|
20184
|
-
if (typeof args2.temperature === "number") {
|
|
20185
|
-
generationConfig.temperature = args2.temperature;
|
|
20186
|
-
}
|
|
20187
|
-
if (Object.keys(generationConfig).length > 0) {
|
|
20188
|
-
request3.generationConfig = generationConfig;
|
|
20189
|
-
}
|
|
20190
|
-
return request3;
|
|
20191
|
-
}
|
|
20192
|
-
|
|
20193
|
-
// packages/agent-runtime/antigravityCloudCodeProvider.ts
|
|
20194
|
-
var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
|
|
20195
|
-
function buildCloudCodeAssistPayload(args2) {
|
|
20196
|
-
const projectId = readAntigravityProjectId(args2.metadata);
|
|
20197
|
-
if (!projectId) {
|
|
20198
|
-
throw new Error(
|
|
20199
|
-
"Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
|
|
20200
|
-
);
|
|
20201
|
-
}
|
|
20202
|
-
const logicalModel = asOptionalTrimmedString(args2.openAiBody.model) ?? asOptionalTrimmedString(args2.agentConfig.model) ?? "gemini-3.1-pro";
|
|
20203
|
-
const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
|
|
20204
|
-
const rawMessages = Array.isArray(args2.openAiBody.messages) ? args2.openAiBody.messages : [];
|
|
20205
|
-
const quirks = resolveGeminiModelQuirks(model);
|
|
20206
|
-
const isClaude = quirks.isClaudeCrossModel;
|
|
20207
|
-
const { contents, systemTexts } = convertOpenAiMessagesToGemini(rawMessages, {
|
|
20208
|
-
attachSkipThoughtSignature: quirks.allowsThoughtSignatureSentinel
|
|
20209
|
-
});
|
|
20210
|
-
if (contents.length === 0) {
|
|
20211
|
-
throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
|
|
20212
|
-
}
|
|
20213
|
-
const prompt = args2.agentConfig.prompt?.trim();
|
|
20214
|
-
if (prompt) systemTexts.unshift(prompt);
|
|
20215
|
-
const request3 = { contents };
|
|
20216
|
-
if (systemTexts.length > 0) {
|
|
20217
|
-
request3.systemInstruction = {
|
|
20218
|
-
role: "user",
|
|
20219
|
-
parts: systemTexts.map((text) => ({ text }))
|
|
20220
|
-
};
|
|
20221
|
-
}
|
|
20222
|
-
const tools = convertOpenAiToolsToGemini(
|
|
20223
|
-
Array.isArray(args2.openAiBody.tools) ? args2.openAiBody.tools : void 0
|
|
20224
|
-
);
|
|
20225
|
-
if (tools) {
|
|
20226
|
-
request3.tools = tools;
|
|
20227
|
-
request3.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
|
|
20228
|
-
}
|
|
20229
|
-
const generationConfig = {};
|
|
20230
|
-
if (profile?.maxOutputTokens) {
|
|
20231
|
-
generationConfig.maxOutputTokens = profile.maxOutputTokens;
|
|
20232
|
-
} else if (typeof args2.agentConfig.max_tokens === "number" && args2.agentConfig.max_tokens > 0) {
|
|
20233
|
-
generationConfig.maxOutputTokens = args2.agentConfig.max_tokens;
|
|
20234
|
-
}
|
|
20235
|
-
if (typeof args2.agentConfig.temperature === "number") {
|
|
20236
|
-
generationConfig.temperature = args2.agentConfig.temperature;
|
|
20237
|
-
}
|
|
20238
|
-
if (Object.keys(generationConfig).length > 0) {
|
|
20239
|
-
request3.generationConfig = generationConfig;
|
|
20240
|
-
}
|
|
20241
|
-
const agentId = randomUUID();
|
|
20242
|
-
const trajectoryId = randomUUID();
|
|
20243
|
-
const step = 2;
|
|
20244
|
-
const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
|
|
20245
|
-
const labels = {
|
|
20246
|
-
trajectory_id: trajectoryId,
|
|
20247
|
-
last_step_index: String(step - 1),
|
|
20248
|
-
used_claude: String(isClaude),
|
|
20249
|
-
used_claude_conservative: String(isClaude)
|
|
20250
|
-
};
|
|
20251
|
-
if (profile?.modelEnum) {
|
|
20252
|
-
labels.model_enum = profile.modelEnum;
|
|
20253
|
-
}
|
|
20254
|
-
request3.labels = labels;
|
|
20255
|
-
request3.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
|
|
20256
|
-
return {
|
|
20257
|
-
url: `${resolveAntigravityCloudCodeBaseUrl(args2.agentConfig.customProviderUrl)}${STREAM_PATH}`,
|
|
20258
|
-
envelope: {
|
|
20259
|
-
project: projectId,
|
|
20260
|
-
model,
|
|
20261
|
-
request: request3,
|
|
20262
|
-
requestId,
|
|
20263
|
-
requestType: "agent",
|
|
20264
|
-
userAgent: "antigravity"
|
|
20265
|
-
}
|
|
20266
|
-
};
|
|
20267
|
-
}
|
|
20268
|
-
function resolveAntigravityFinishReason(upstream) {
|
|
20269
|
-
const normalized = (upstream ?? "").trim().toUpperCase();
|
|
20270
|
-
if (normalized === "MAX_TOKENS") return "length";
|
|
20271
|
-
if (normalized === "SAFETY" || normalized === "RECITATION" || normalized === "PROHIBITED_CONTENT" || normalized === "BLOCKLIST") {
|
|
20272
|
-
return "content_filter";
|
|
20273
|
-
}
|
|
20274
|
-
return "stop";
|
|
20275
|
-
}
|
|
20276
|
-
function normalizeAntigravityCompletion(decoded) {
|
|
20277
|
-
const { text, toolCalls, usage, finishReason, reasoningContent, events } = decoded;
|
|
20278
|
-
const normalizedFinishReason = (finishReason ?? "").trim().toUpperCase();
|
|
20279
|
-
if (!text && !reasoningContent && toolCalls.length === 0 && !finishReason && !usage) {
|
|
20280
|
-
const body = {
|
|
20281
|
-
error: {
|
|
20282
|
-
message: "antigravity upstream returned an empty stream (no content, finishReason or usage); channel degradation, not model emptiness"
|
|
20283
|
-
},
|
|
20284
|
-
provider_events: events
|
|
20285
|
-
};
|
|
20286
|
-
return {
|
|
20287
|
-
status: 502,
|
|
20288
|
-
text: "",
|
|
20289
|
-
toolCalls: [],
|
|
20290
|
-
providerEvents: events,
|
|
20291
|
-
body
|
|
20292
|
-
};
|
|
20293
|
-
}
|
|
20294
|
-
if (normalizedFinishReason === "MALFORMED_FUNCTION_CALL") {
|
|
20295
|
-
const message2 = "antigravity upstream returned MALFORMED_FUNCTION_CALL (model generated an invalid function call or tool arguments were rejected by upstream)";
|
|
20296
|
-
const providerFailure = {
|
|
20297
|
-
kind: "provider_failure",
|
|
20298
|
-
provider: "antigravity",
|
|
20299
|
-
code: "MALFORMED_FUNCTION_CALL",
|
|
20300
|
-
message: message2,
|
|
20301
|
-
providerReason: "MALFORMED_FUNCTION_CALL",
|
|
20302
|
-
retryable: false,
|
|
20303
|
-
status: 502
|
|
20304
|
-
};
|
|
20305
|
-
return {
|
|
20306
|
-
status: 502,
|
|
20307
|
-
text: "",
|
|
20308
|
-
toolCalls: [],
|
|
20309
|
-
finishReason,
|
|
20310
|
-
providerEvents: events,
|
|
20311
|
-
providerFailure,
|
|
20312
|
-
runtimeProviderFailure: {
|
|
20313
|
-
message: providerFailure.message,
|
|
20314
|
-
retryable: providerFailure.retryable
|
|
20315
|
-
},
|
|
20316
|
-
body: {
|
|
20317
|
-
error: {
|
|
20318
|
-
message: message2,
|
|
20319
|
-
code: "MALFORMED_FUNCTION_CALL",
|
|
20320
|
-
category: "malformed_function_call",
|
|
20321
|
-
providerReason: "MALFORMED_FUNCTION_CALL",
|
|
20322
|
-
retryable: false
|
|
20323
|
-
},
|
|
20324
|
-
provider_failure: providerFailure,
|
|
20325
|
-
provider_events: events
|
|
20326
|
-
}
|
|
20327
|
-
};
|
|
20328
|
-
}
|
|
20329
|
-
const message = {
|
|
20330
|
-
role: "assistant",
|
|
20331
|
-
content: text || null
|
|
20332
|
-
};
|
|
20333
|
-
if (toolCalls.length > 0) message.tool_calls = toolCalls;
|
|
20334
|
-
if (reasoningContent) message.reasoning_content = reasoningContent;
|
|
20335
|
-
return {
|
|
20336
|
-
status: 200,
|
|
20337
|
-
text,
|
|
20338
|
-
...reasoningContent ? { reasoningContent } : {},
|
|
20339
|
-
toolCalls,
|
|
20340
|
-
...usage ? { usage } : {},
|
|
20341
|
-
...finishReason ? { finishReason } : {},
|
|
20342
|
-
providerEvents: events,
|
|
20343
|
-
body: {
|
|
20344
|
-
choices: [{
|
|
20345
|
-
index: 0,
|
|
20346
|
-
message,
|
|
20347
|
-
finish_reason: toolCalls.length > 0 ? "tool_calls" : resolveAntigravityFinishReason(finishReason)
|
|
20348
|
-
}],
|
|
20349
|
-
...usage ? { usage } : {},
|
|
20350
|
-
provider_events: events
|
|
20351
|
-
}
|
|
20352
|
-
};
|
|
20353
|
-
}
|
|
20354
|
-
async function fetchAntigravityCloudCodeCompletion(args2) {
|
|
20355
|
-
const fetchImpl = args2.fetchImpl ?? fetch;
|
|
20356
|
-
const { url, envelope } = buildCloudCodeAssistPayload(args2);
|
|
20357
|
-
const response = await fetchImpl(url, {
|
|
20358
|
-
method: "POST",
|
|
20359
|
-
headers: {
|
|
20360
|
-
Authorization: `Bearer ${args2.accessToken}`,
|
|
20361
|
-
"Content-Type": "application/json",
|
|
20362
|
-
"User-Agent": getAntigravityUserAgent()
|
|
20363
|
-
},
|
|
20364
|
-
body: JSON.stringify(envelope),
|
|
20365
|
-
signal: args2.signal
|
|
20366
|
-
});
|
|
20367
|
-
if (!response.ok) {
|
|
20368
|
-
const errorText = await response.text();
|
|
20369
|
-
return {
|
|
20370
|
-
status: response.status,
|
|
20371
|
-
text: "",
|
|
20372
|
-
toolCalls: [],
|
|
20373
|
-
providerEvents: [],
|
|
20374
|
-
// 保留上游结构:Antigravity 的限流 body 同样携带结构化的重置信息,
|
|
20375
|
-
// 压成字符串会让冷却退化成 5 分钟默认值。
|
|
20376
|
-
body: parseUpstreamErrorBody(errorText, response.statusText)
|
|
20377
|
-
};
|
|
20378
|
-
}
|
|
20379
|
-
const chunkStream = streamSseDataValues(response, parseSseDataLineJson);
|
|
20380
|
-
const { text, toolCalls, usage, finishReason, reasoningContent, events } = await accumulateGeminiStream(chunkStream, {
|
|
20381
|
-
onTextDelta: args2.onTextDelta,
|
|
20382
|
-
onReasoningDelta: args2.onReasoningDelta
|
|
20383
|
-
});
|
|
20384
|
-
const normalized = normalizeAntigravityCompletion({
|
|
20385
|
-
text,
|
|
20386
|
-
toolCalls,
|
|
20387
|
-
usage,
|
|
20388
|
-
finishReason,
|
|
20389
|
-
reasoningContent,
|
|
20390
|
-
events
|
|
20391
|
-
});
|
|
20392
|
-
if (normalized.status !== 200 || !text && toolCalls.length === 0) {
|
|
20393
|
-
console.warn(
|
|
20394
|
-
`[antigravity] empty completion: finishReason=${JSON.stringify(finishReason)} reasoningLen=${reasoningContent?.length ?? 0} usage=${JSON.stringify(usage) ?? "none"} model=${String(envelope.model)} base=${new URL(url).host}`
|
|
20395
|
-
);
|
|
20396
|
-
}
|
|
20397
|
-
return normalized;
|
|
20130
|
+
// packages/agent-runtime/sessionIdentity.ts
|
|
20131
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
20132
|
+
var SALT = "nolo-session-identity-v1";
|
|
20133
|
+
function isStableSessionIdentityEnabled(env = process.env) {
|
|
20134
|
+
const v = env.NOLO_STABLE_SESSION_IDENTITY?.trim().toLowerCase();
|
|
20135
|
+
return !(v === "0" || v === "false" || v === "off");
|
|
20136
|
+
}
|
|
20137
|
+
function deriveStableUuid(sessionKey, purpose) {
|
|
20138
|
+
const h = createHash4("sha256").update(`${SALT}\0${purpose}\0${sessionKey}`).digest();
|
|
20139
|
+
h[6] = h[6] & 15 | 80;
|
|
20140
|
+
h[8] = h[8] & 63 | 128;
|
|
20141
|
+
const x = h.subarray(0, 16).toString("hex");
|
|
20142
|
+
return `${x.slice(0, 8)}-${x.slice(8, 12)}-${x.slice(12, 16)}-${x.slice(16, 20)}-${x.slice(20, 32)}`;
|
|
20143
|
+
}
|
|
20144
|
+
function resolveSessionKey(args2) {
|
|
20145
|
+
const d = args2.dialogId?.trim();
|
|
20146
|
+
return d ? `dialog:${d}` : void 0;
|
|
20398
20147
|
}
|
|
20399
20148
|
|
|
20400
20149
|
// packages/agent-runtime/devin/devinProvider.ts
|
|
20401
20150
|
import { randomBytes, randomUUID as randomUUID2 } from "node:crypto";
|
|
20402
20151
|
var CLIENT_NAME = "chisel";
|
|
20403
|
-
var CLIENT_VERSION = "
|
|
20152
|
+
var CLIENT_VERSION = "3000.11.3";
|
|
20404
20153
|
function writeVarint(fieldNum, value) {
|
|
20405
20154
|
const tag = fieldNum << 3 | 0;
|
|
20406
20155
|
const bytes = [];
|
|
@@ -20457,10 +20206,13 @@ function encodeDevinClientMetadata(token) {
|
|
|
20457
20206
|
writeStringField(31, generateFingerprint())
|
|
20458
20207
|
]);
|
|
20459
20208
|
}
|
|
20460
|
-
function
|
|
20209
|
+
function devinId(id, purpose) {
|
|
20210
|
+
return id?.sessionKey && isStableSessionIdentityEnabled() ? deriveStableUuid(id.sessionKey, purpose) : randomUUID2();
|
|
20211
|
+
}
|
|
20212
|
+
function encodeDevinChatMessage(msg, identity2, index = 0) {
|
|
20461
20213
|
const source = msg.role === "assistant" ? 2 : msg.role === "tool" ? 4 : 1;
|
|
20462
20214
|
return Buffer.concat([
|
|
20463
|
-
writeStringField(1,
|
|
20215
|
+
writeStringField(1, devinId(identity2, `msg:${index}:${msg.role}`)),
|
|
20464
20216
|
writeVarint(2, source),
|
|
20465
20217
|
writeStringField(3, msg.text),
|
|
20466
20218
|
...(msg.toolCalls ?? []).map(
|
|
@@ -20516,6 +20268,7 @@ function buildCompletionConfig(params) {
|
|
|
20516
20268
|
}
|
|
20517
20269
|
function buildGetChatMessageRequest(params) {
|
|
20518
20270
|
const { token, messages, model, tools = [], temperature } = params;
|
|
20271
|
+
const identity2 = { sessionKey: params.sessionKey };
|
|
20519
20272
|
const metadata = encodeDevinClientMetadata(token);
|
|
20520
20273
|
let systemPrompt = "";
|
|
20521
20274
|
const filteredMessages = [];
|
|
@@ -20545,7 +20298,7 @@ ${item.text}`;
|
|
|
20545
20298
|
coalesced.push({ ...item });
|
|
20546
20299
|
}
|
|
20547
20300
|
}
|
|
20548
|
-
const chatMessageBuffers = coalesced.map((m) => encodeDevinChatMessage(m));
|
|
20301
|
+
const chatMessageBuffers = coalesced.map((m, i) => encodeDevinChatMessage(m, identity2, i));
|
|
20549
20302
|
const completionConfig = buildCompletionConfig({ temperature });
|
|
20550
20303
|
const modelConfig = Buffer.concat([
|
|
20551
20304
|
writeStringField(1, randomUUID2()),
|
|
@@ -20775,6 +20528,11 @@ function decodeDevinResponsePayload(payload) {
|
|
|
20775
20528
|
}
|
|
20776
20529
|
return { content, reasoning, finishReason, events, usage };
|
|
20777
20530
|
}
|
|
20531
|
+
function isMeaningfulDevinEvent(event) {
|
|
20532
|
+
if (event.type === "reasoning" || event.type === "content") return event.text.length > 0;
|
|
20533
|
+
if (event.type === "tool-call-start") return !!event.name;
|
|
20534
|
+
return event.argsDelta.length > 0;
|
|
20535
|
+
}
|
|
20778
20536
|
function createDevinProvider(options) {
|
|
20779
20537
|
const { token, model = "swe-2-max", fetchImpl = fetch, tools = [], temperature } = options;
|
|
20780
20538
|
return {
|
|
@@ -20786,9 +20544,11 @@ function createDevinProvider(options) {
|
|
|
20786
20544
|
messages,
|
|
20787
20545
|
model: selectedModel,
|
|
20788
20546
|
tools,
|
|
20789
|
-
temperature
|
|
20547
|
+
temperature,
|
|
20548
|
+
sessionKey: resolveSessionKey({ dialogId: opts?.dialogId })
|
|
20790
20549
|
});
|
|
20791
20550
|
const frame = buildDevinConnectFrame(requestPayload);
|
|
20551
|
+
const timingTracker = createProviderCallTimingTracker();
|
|
20792
20552
|
const response = await fetchImpl(DEVIN_CONNECT_URL, {
|
|
20793
20553
|
method: "POST",
|
|
20794
20554
|
headers: {
|
|
@@ -20846,6 +20606,7 @@ function createDevinProvider(options) {
|
|
|
20846
20606
|
reasoning += delta.reasoning;
|
|
20847
20607
|
if (delta.finishReason) finishReason = delta.finishReason;
|
|
20848
20608
|
for (const event of delta.events) {
|
|
20609
|
+
if (isMeaningfulDevinEvent(event)) observeMeaningfulProviderResponse(timingTracker);
|
|
20849
20610
|
if (event.type === "reasoning") {
|
|
20850
20611
|
opts?.onReasoningDelta?.(event.text);
|
|
20851
20612
|
} else if (event.type === "content") {
|
|
@@ -20894,13 +20655,14 @@ function createDevinProvider(options) {
|
|
|
20894
20655
|
if (!text && !reasoning && toolCalls.length === 0) {
|
|
20895
20656
|
throw new Error("Devin Connect upstream completed without content or tool calls");
|
|
20896
20657
|
}
|
|
20897
|
-
const
|
|
20658
|
+
const timing = finalizeProviderCallTiming(timingTracker);
|
|
20659
|
+
const usage = frameUsage ? withProviderCallTimingFields({
|
|
20898
20660
|
prompt_tokens: frameUsage.prompt + frameUsage.cacheRead,
|
|
20899
20661
|
completion_tokens: frameUsage.completion ?? 0,
|
|
20900
20662
|
total_tokens: frameUsage.prompt + frameUsage.cacheRead + (frameUsage.completion ?? 0) + frameUsage.cacheWrite,
|
|
20901
20663
|
...frameUsage.cacheRead > 0 ? { prompt_tokens_details: { cached_tokens: frameUsage.cacheRead } } : {},
|
|
20902
20664
|
...frameUsage.cacheWrite > 0 ? { cache_creation_input_tokens: frameUsage.cacheWrite } : {}
|
|
20903
|
-
} : void 0;
|
|
20665
|
+
}, timing) : void 0;
|
|
20904
20666
|
return {
|
|
20905
20667
|
content: text,
|
|
20906
20668
|
model: selectedModel,
|
|
@@ -20922,20 +20684,16 @@ function createDevinProvider(options) {
|
|
|
20922
20684
|
}
|
|
20923
20685
|
|
|
20924
20686
|
export {
|
|
20687
|
+
readCommandActionGatePayload,
|
|
20688
|
+
readActionGate,
|
|
20925
20689
|
Option_exports,
|
|
20926
20690
|
Duration_exports,
|
|
20927
20691
|
Exit_exports,
|
|
20928
20692
|
Effect_exports,
|
|
20929
|
-
readCommandActionGatePayload,
|
|
20930
|
-
readActionGate,
|
|
20931
|
-
evaluateFileWritePolicy,
|
|
20932
|
-
summarizeToolArguments,
|
|
20933
20693
|
formatToolOverflowMarker,
|
|
20934
20694
|
LOCAL_AGENT_CONFIG_MISSING_CODE,
|
|
20935
20695
|
LOCAL_TURN_ABORTED_CODE,
|
|
20936
20696
|
runLocalAgentTurn,
|
|
20937
|
-
parseSseDataLineJson,
|
|
20938
|
-
parseSseDataLineObject,
|
|
20939
20697
|
codexStreamFailureStatus,
|
|
20940
20698
|
aggregateResponsesStream,
|
|
20941
20699
|
buildOpenAiCompatibleChatCompletionRequest,
|
|
@@ -20969,13 +20727,9 @@ export {
|
|
|
20969
20727
|
buildLocalDialogWritePlan,
|
|
20970
20728
|
buildNoloWorkspaceCliToolExecutors,
|
|
20971
20729
|
buildLoadSkillExecutor,
|
|
20972
|
-
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
shouldUseGeminiNativeToolRoute,
|
|
20976
|
-
buildGeminiGenerateContentRequest,
|
|
20977
|
-
resolveAntigravityFinishReason,
|
|
20978
|
-
fetchAntigravityCloudCodeCompletion,
|
|
20730
|
+
isStableSessionIdentityEnabled,
|
|
20731
|
+
deriveStableUuid,
|
|
20732
|
+
resolveSessionKey,
|
|
20979
20733
|
readDevinUpstreamFailure,
|
|
20980
20734
|
createDevinProvider
|
|
20981
20735
|
};
|