nolo-cli 0.80.0-alpha.1 → 0.80.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 +2 -2
- package/{_executeModel-T3FPYFVF.js → _executeModel-UXVEB3GO.js} +46 -46
- package/{action-D22U6CTH.js → action-YVYQEAAV.js} +11 -11
- package/{addContentAction-XAPUTGL4.js → addContentAction-O7R66HEX.js} +9 -9
- package/{addDialogAgentAction-M7VLLBZM.js → addDialogAgentAction-74OA7KYP.js} +8 -8
- package/{agentDeleteCommand-2TYFURBN.js → agentDeleteCommand-OODHSL4K.js} +30 -28
- package/{agentEmailCommands-7P35ZMUA.js → agentEmailCommands-3R73WSCD.js} +64 -60
- package/{agentGrantCommands-R3VQEZJR.js → agentGrantCommands-M3XFO6EN.js} +2 -2
- package/{agentListCommands-IFUOWXP3.js → agentListCommands-TBTEXV2E.js} +38 -30
- package/{agentMachineCommands-G46ZZ2ZQ.js → agentMachineCommands-3GKE6ZHG.js} +30 -28
- package/{agentProviderCommands-65ZC2WB4.js → agentProviderCommands-GNPTL5XR.js} +87 -0
- package/{agentPullCommand-N7L2CT7L.js → agentPullCommand-O5MPVJ5E.js} +3 -3
- package/{agentRecordCommands-R74LTQEQ.js → agentRecordCommands-3664GLRE.js} +61 -57
- package/{agentRunCommand-UKJAECQ6.js → agentRunCommand-YNSEOBTR.js} +62 -58
- package/{agentRunControl-T44MESII.js → agentRunControl-XLGD3UZ5.js} +1 -1
- package/{agentRuntimeLocal-PUZINLWJ.js → agentRuntimeLocal-5BX6PI4X.js} +28 -26
- package/{agentSlice-EACXUOWW.js → agentSlice-KTVOEUDX.js} +10 -10
- package/{appDeleteCommands-U4NTEJYQ.js → appDeleteCommands-UNTBD55Y.js} +30 -28
- package/{appDeployCommands-FXF45Q7F.js → appDeployCommands-LOF4JNBZ.js} +30 -28
- package/{appDeployStatusCommands-KONVRM53.js → appDeployStatusCommands-MMLE6BDW.js} +30 -28
- package/{appGetCommands-3VOGIZ7T.js → appGetCommands-WFJAJK6B.js} +30 -28
- package/{appListCommands-A6ROBW7P.js → appListCommands-NC265RGX.js} +30 -28
- package/{authCommand-EVGFLAHO.js → authCommand-F4EFRRX6.js} +164 -24
- package/{authCommands-ILTBI6JV.js → authCommands-RGOGCPP6.js} +4 -5
- package/builtinSkillRegistry-FUAVTRVZ.js +33 -0
- package/{chatQueueReduxAdapter-XEIJO5WR.js → chatQueueReduxAdapter-4YQF4NHY.js} +24 -24
- package/{chromeCommands-VOIRNJBL.js → chromeCommands-FZYAU75D.js} +1 -1
- package/{chromeOpsCommands-M7DPCX2T.js → chromeOpsCommands-62P2Q2YB.js} +31 -1
- package/{chunk-C3FZR5EC.js → chunk-2F7RJC6L.js} +1 -1
- package/{chunk-MGU5ADIQ.js → chunk-35EWBHJO.js} +10 -10
- package/{chunk-HQUORJTM.js → chunk-3BMYXEUW.js} +1 -1
- package/{chunk-3QPYFHAH.js → chunk-3DII57IT.js} +1 -1
- package/{chunk-KIS76A2P.js → chunk-3IIEFNGY.js} +38 -4
- package/{chunk-MEVSATIF.js → chunk-4OZYL5FG.js} +66 -792
- package/{chunk-GBPZKFYK.js → chunk-53HEEOTT.js} +4 -4
- package/{chunk-5XTOKQLW.js → chunk-5UTFL4QJ.js} +6 -2
- package/chunk-5ZUL4CUO.js +10 -0
- package/{chunk-E6RGHPDR.js → chunk-6D6VBVEW.js} +4 -6
- package/{chunk-CMH2SYHX.js → chunk-6OZ36FXI.js} +2 -2
- package/{chunk-QA6YKM3H.js → chunk-76WEAXJB.js} +49 -10
- package/{chunk-BYEJ7K2Z.js → chunk-7S4YWN7P.js} +1 -1
- package/{chunk-SREASRV5.js → chunk-ABQYVJBJ.js} +1 -1
- package/chunk-ACTMNVHM.js +93 -0
- package/{chunk-XWNRAIUL.js → chunk-AFUORTY4.js} +6 -16
- package/{chunk-AFIWC5NH.js → chunk-BLJWCTRL.js} +1 -1
- package/chunk-BNGW5ASC.js +344 -0
- package/{chunk-SZLVDREM.js → chunk-BP4XNZRM.js} +3 -3
- package/{chunk-2KDR4CWE.js → chunk-BYMV6QZG.js} +24 -1
- package/{chunk-HH65VA5U.js → chunk-CPH3W5A7.js} +15 -3
- package/{chunk-U6LKJRJB.js → chunk-D2P6UDPQ.js} +42 -26
- package/{chunk-L2Y24GRM.js → chunk-DEUUPHOO.js} +16 -12
- package/{chunk-MYU3MJCF.js → chunk-DHDMC6FO.js} +175 -7
- package/{chunk-CDVGNZDA.js → chunk-EFVDQUCT.js} +11 -173
- package/{chunk-EXMHJN7C.js → chunk-EYAQT56M.js} +4 -3
- package/{chunk-733J6D44.js → chunk-FLLFOP5L.js} +6 -6
- package/{chunk-H7UKKEIS.js → chunk-GFD4ALW3.js} +1 -1
- package/{chunk-PYXL2CJL.js → chunk-GPCZ7UXG.js} +1 -1
- package/{chunk-K7AG465Q.js → chunk-GQBOR3G6.js} +4 -2
- package/{chunk-QUH3XHL5.js → chunk-H3PIH2EO.js} +7 -7
- package/{chunk-YFADVSZE.js → chunk-H62HCIUP.js} +6 -6
- package/{chunk-PZM3EENV.js → chunk-HJUYAD4A.js} +1 -1
- package/{chunk-ALGK6TIE.js → chunk-HMPEO3ZE.js} +3 -3
- package/{chunk-3JQ2NRYU.js → chunk-HVURBGF3.js} +4 -4
- package/{chunk-FPTQQSS6.js → chunk-IAO6JBYW.js} +26 -5
- package/{chunk-V3ZKNK5D.js → chunk-IIVGDG4I.js} +11 -10
- package/{chunk-UDQWGU7F.js → chunk-J4MOO56S.js} +1 -1
- package/{chunk-DSRXPQWA.js → chunk-JAXOVNM4.js} +43 -43
- package/{chunk-KC5FAHVS.js → chunk-JEDZAO7L.js} +1 -1
- package/{chunk-6XIE5ZGI.js → chunk-JPGCXHNM.js} +1 -1
- package/chunk-JRQFUXY7.js +1625 -0
- package/chunk-KQ4ONNQD.js +677 -0
- package/{chunk-D74EWXL4.js → chunk-LBEDNSMY.js} +419 -72
- package/{chunk-X7Z7U4Z6.js → chunk-LIIKM7DD.js} +15 -15
- package/{chunk-RXX4GDIH.js → chunk-LS2ZANRJ.js} +1 -1
- package/{chunk-BJIRLHJR.js → chunk-M2EJHDJP.js} +4 -0
- package/{chunk-EVBFYPDC.js → chunk-MC4XLIJ7.js} +6 -2
- package/{chunk-G3NT6BM3.js → chunk-MPV6E6WR.js} +608 -60
- package/{chunk-ZY4K4CZR.js → chunk-MWAO7TZZ.js} +909 -304
- package/{chunk-QRBAZ5PW.js → chunk-NKRYKK7T.js} +3 -3
- package/{chunk-ZLPA7K55.js → chunk-OA6Q2A4I.js} +29 -10
- package/{chunk-QC5LGHYP.js → chunk-OF7AQZUG.js} +10 -5
- package/{chunk-UJ63UXGE.js → chunk-OIVSQH2O.js} +1006 -801
- package/{chunk-AETZ7AD6.js → chunk-Q554LLSI.js} +1 -1
- package/chunk-Q5FJJ6XI.js +103 -0
- package/{chunk-AJHEFRGJ.js → chunk-Q67DOFOO.js} +214 -5
- package/{chunk-UZ6XXCVR.js → chunk-QDSINZM3.js} +15 -2
- package/{chunk-AFIKMMGC.js → chunk-QIAVMDHY.js} +1 -1
- package/{chunk-QCZX4FTW.js → chunk-SH43IESU.js} +173 -15
- package/{chunk-FSFQ3A7S.js → chunk-SNPMM7H3.js} +137 -12
- package/{chunk-P7FA2HMM.js → chunk-SQZDZXP5.js} +13 -15
- package/{chunk-SPAQ4PVV.js → chunk-SV5IJK6K.js} +1 -1
- package/{chunk-BJCWNHVU.js → chunk-TOP2VXOR.js} +2 -2
- package/{chunk-EOU7ZSTU.js → chunk-TRCMIJA7.js} +1198 -50
- package/{chunk-4EJ5QYB5.js → chunk-UKZDAFYT.js} +1 -1
- package/{chunk-PGSKWZCB.js → chunk-UZGQNTVW.js} +1 -1
- package/{chunk-ZZCJUXUI.js → chunk-V4MJDUSR.js} +2 -2
- package/{chunk-JYYZCK2Z.js → chunk-V7E4PXQD.js} +1 -1
- package/{chunk-OZX2IPKM.js → chunk-VLTIYV3X.js} +1 -1
- package/{chunk-NHRQCXIQ.js → chunk-VMFTFOWF.js} +13 -3
- package/{chunk-E36HZARC.js → chunk-WADCY6G6.js} +3 -3
- package/{chunk-5J7W2VWW.js → chunk-WV42OMV7.js} +6 -265
- package/{chunk-DWPNOYMB.js → chunk-YQTQQX2H.js} +1 -1
- package/{chunk-Q6FF2MCK.js → chunk-Z77CRGTW.js} +1 -1
- package/{contentThunks-3SPROFG5.js → contentThunks-2USKJBI4.js} +25 -25
- package/{createAgentAutomationAction-EIP2EG3O.js → createAgentAutomationAction-NTLU42X2.js} +25 -25
- package/{createDialogAction-RLUSTN4D.js → createDialogAction-UCYF4BUN.js} +28 -28
- package/{createPageAction-4Y52G7WG.js → createPageAction-QFGUGZ5M.js} +26 -26
- package/{dbSlice-GKGGFNOB.js → dbSlice-XVWBAGYN.js} +8 -8
- package/{deleteFile-LWSR674W.js → deleteFile-YG6QMJLU.js} +3 -3
- package/{dialogCommands-G223U5WU.js → dialogCommands-X4OB6SC6.js} +34 -30
- package/{dialogSlice-THY45JWM.js → dialogSlice-HQFQIQDZ.js} +24 -24
- package/{docCreateCommands-2P47IJDK.js → docCreateCommands-DFST4PFR.js} +31 -29
- package/{docDeleteCommands-N3EGDOIC.js → docDeleteCommands-V37JZOSP.js} +32 -30
- package/{docReadCommands-6BFV2HI7.js → docReadCommands-Z64VDPDQ.js} +31 -29
- package/{docStore-ZQ3ECOPY.js → docStore-GVWEDN5E.js} +9 -9
- package/{docUpdateCommands-ZTMPXHC5.js → docUpdateCommands-I6FB6ENK.js} +31 -29
- package/{fetchMessages-DRABNDPZ.js → fetchMessages-EIU7UFFK.js} +3 -4
- package/{getPricing-HRMSOF3E.js → getPricing-LUSEABA6.js} +4 -4
- package/{handleSendMessageAction-CE4M5XIE.js → handleSendMessageAction-TLB2SAU4.js} +24 -24
- package/index.js +101 -84
- package/{localDialogRead-PUQKFI73.js → localDialogRead-BTFJ4V2I.js} +2 -2
- package/{localRuntimeDb-P37ZTX55.js → localRuntimeDb-SYQGUF4U.js} +1 -1
- package/{machineCommands-4OT7KVCD.js → machineCommands-PV5XA7UF.js} +61 -57
- package/{machineWsRunDispatch-TR3EYESP.js → machineWsRunDispatch-W2DPC7TZ.js} +59 -55
- package/{memberThunks-KATHH3F4.js → memberThunks-QGFLFVCI.js} +9 -9
- package/{models-GS72DVJS.js → models-T3SG6MJ5.js} +2 -2
- package/{offlineMarxistsAgentCommand-GEH6SNNA.js → offlineMarxistsAgentCommand-HGXZV4XJ.js} +1 -1
- package/package.json +1 -1
- package/providerPresetApply-FG6NZ57W.js +214 -0
- package/providerRegistry-757OWH3O.js +31 -0
- package/{read-LC6HVYBN.js → read-COE3ZYR6.js} +5 -4
- package/{readDocTool-N3ERJHHF.js → readDocTool-5USN4A6V.js} +1 -1
- package/{readlineWorkspace-RE3P324X.js → readlineWorkspace-PHZXJKJM.js} +194 -109
- package/{removeDialogAgentAction-F5GPTALR.js → removeDialogAgentAction-IX3MN2ZO.js} +11 -11
- package/{runAgentClientLoop-NE5EHXSS.js → runAgentClientLoop-26DG6ZEY.js} +45 -45
- package/{runtimeDoctorCommands-CROTMULY.js → runtimeDoctorCommands-X6WDBEQX.js} +2 -2
- package/{setDialogExtraReferencesAction-AY4ZCF3A.js → setDialogExtraReferencesAction-X4HCPNZL.js} +9 -9
- package/{setPrimaryDialogAgentAction-HPMG7V3R.js → setPrimaryDialogAgentAction-4GMIQLOD.js} +11 -11
- package/{settingSlice-OEJA4NQO.js → settingSlice-ZQZVUPKK.js} +10 -10
- package/{spaceCommands-MRP5U3C3.js → spaceCommands-3QH2QFNW.js} +29 -27
- package/{streamAgentChatTurn-A6L6O22P.js → streamAgentChatTurn-BY7IPY5C.js} +57 -56
- package/{switchDialogAgentAction-HMDZTZ4I.js → switchDialogAgentAction-N52LRPA3.js} +8 -8
- package/{tableCommands-SUNTHAYX.js → tableCommands-O6NWHFKV.js} +1 -1
- package/{toolApiClient-VGYUB4P5.js → toolApiClient-QVJ6HDNN.js} +2 -2
- package/{tools-JS475NYO.js → tools-4Y2EYH5D.js} +41 -39
- package/tuiSummaryLlmCaller-T2SHYMDZ.js +127 -0
- package/{updateCommands-Y363MC3L.js → updateCommands-2M74UL7P.js} +2 -2
- package/{updateDialogTitleAction-GMZUT6RP.js → updateDialogTitleAction-2S4DCP35.js} +45 -28
- package/chunk-3IT2PFHL.js +0 -611
- package/chunk-I42VC5KR.js +0 -15
- package/chunk-NG4UT4K4.js +0 -79
- package/codingSkills-E6KSDNSJ.js +0 -48
- package/tuiSummaryLlmCaller-3Z24VUWM.js +0 -116
- package/{chunk-3RAG2NAD.js → chunk-UKWGR5SS.js} +3 -3
- package/{db-VQSAOWAO.js → db-WK5MDZVN.js} +1 -1
- package/{localRuntimeAuthority-R5UBODT3.js → localRuntimeAuthority-6IR6BBXE.js} +3 -3
|
@@ -8,15 +8,19 @@ import {
|
|
|
8
8
|
readSseFrames,
|
|
9
9
|
streamSseDataValues,
|
|
10
10
|
throwIfChatCompletionStreamFailed
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-OF7AQZUG.js";
|
|
12
|
+
import {
|
|
13
|
+
DEVIN_CONNECT_URL
|
|
14
|
+
} from "./chunk-Q5FJJ6XI.js";
|
|
12
15
|
import {
|
|
13
16
|
clipToolText,
|
|
14
17
|
hasImageInRuntimeMessages,
|
|
18
|
+
resolveAgentContextWindow,
|
|
15
19
|
resolveAgentImageInputSupport,
|
|
16
20
|
resolveHistoricalToolContentCap,
|
|
17
21
|
resolveToolOutputProfile,
|
|
18
22
|
stripImagePartsFromMessages
|
|
19
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-3IIEFNGY.js";
|
|
20
24
|
import {
|
|
21
25
|
downgradeUnparsableToolCalls,
|
|
22
26
|
hasParsableObjectArguments,
|
|
@@ -40,7 +44,7 @@ import {
|
|
|
40
44
|
requiresBareImageUrl,
|
|
41
45
|
resolveToolGuidedSections,
|
|
42
46
|
toBareImageUrlMessages
|
|
43
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-OA6Q2A4I.js";
|
|
44
48
|
import {
|
|
45
49
|
convertMessagesToResponsesInput,
|
|
46
50
|
extractReasoningFromResponseOutput,
|
|
@@ -51,15 +55,6 @@ import {
|
|
|
51
55
|
toOpenAiCompatibleMessages,
|
|
52
56
|
toResponsesTools
|
|
53
57
|
} from "./chunk-PUOC4YRO.js";
|
|
54
|
-
import {
|
|
55
|
-
getAntigravityUserAgent,
|
|
56
|
-
readAntigravityProjectId,
|
|
57
|
-
resolveAntigravityCloudCodeBaseUrl
|
|
58
|
-
} from "./chunk-PGSKWZCB.js";
|
|
59
|
-
import {
|
|
60
|
-
buildProviderAuthHeaders,
|
|
61
|
-
buildProviderExecutionPlan
|
|
62
|
-
} from "./chunk-CMH2SYHX.js";
|
|
63
58
|
import {
|
|
64
59
|
BRIDGE_STREAM_MAX_CHARS,
|
|
65
60
|
DEFAULT_READ_DIALOG_MAX_RESPONSE_CHARS,
|
|
@@ -73,7 +68,16 @@ import {
|
|
|
73
68
|
parseNoloWorkspaceToolArguments,
|
|
74
69
|
readTextStreamUpToChars,
|
|
75
70
|
resolveNoloDialogInput
|
|
76
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-IIVGDG4I.js";
|
|
72
|
+
import {
|
|
73
|
+
getAntigravityUserAgent,
|
|
74
|
+
readAntigravityProjectId,
|
|
75
|
+
resolveAntigravityCloudCodeBaseUrl
|
|
76
|
+
} from "./chunk-UZGQNTVW.js";
|
|
77
|
+
import {
|
|
78
|
+
buildProviderAuthHeaders,
|
|
79
|
+
buildProviderExecutionPlan
|
|
80
|
+
} from "./chunk-6OZ36FXI.js";
|
|
77
81
|
import {
|
|
78
82
|
buildDialogFallbackTitleFromUserInput
|
|
79
83
|
} from "./chunk-2MBTWINN.js";
|
|
@@ -87,7 +91,7 @@ import {
|
|
|
87
91
|
resolveEmptyAssistantFallbackMessage,
|
|
88
92
|
resolveEmptyAssistantOutcome,
|
|
89
93
|
resolveTruncatedReasoningTailLog
|
|
90
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-JAXOVNM4.js";
|
|
91
95
|
import {
|
|
92
96
|
COMPACTION_SUMMARY_SCHEMA_VERSION,
|
|
93
97
|
COMPACTION_SUMMARY_SYSTEM_PROMPT,
|
|
@@ -106,7 +110,7 @@ import {
|
|
|
106
110
|
resolveCompressionTriggerRatio,
|
|
107
111
|
truncateToolOutputForContext,
|
|
108
112
|
withProviderCallTimingFields
|
|
109
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-WADCY6G6.js";
|
|
110
114
|
import {
|
|
111
115
|
estimateTokenCount
|
|
112
116
|
} from "./chunk-PSCNXBYA.js";
|
|
@@ -130,27 +134,25 @@ import {
|
|
|
130
134
|
asRecordOrEmpty
|
|
131
135
|
} from "./chunk-KX6YBIHG.js";
|
|
132
136
|
import {
|
|
137
|
+
asTrimmedNonEmptyStringArray,
|
|
133
138
|
dialogMessageKey,
|
|
134
139
|
dialogMessageRange
|
|
135
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-VMFTFOWF.js";
|
|
136
141
|
import {
|
|
137
142
|
asOptionalFiniteNumber
|
|
138
143
|
} from "./chunk-WWC7I6TA.js";
|
|
139
|
-
import {
|
|
140
|
-
asTrimmedNonEmptyStringArray
|
|
141
|
-
} from "./chunk-I42VC5KR.js";
|
|
142
144
|
import {
|
|
143
145
|
asTrimmedLowercaseString
|
|
144
146
|
} from "./chunk-QSJ3HFEF.js";
|
|
147
|
+
import {
|
|
148
|
+
isRecord
|
|
149
|
+
} from "./chunk-KUG52IAP.js";
|
|
145
150
|
import {
|
|
146
151
|
asTrimmedString
|
|
147
152
|
} from "./chunk-3EUW3WEO.js";
|
|
148
153
|
import {
|
|
149
154
|
asOptionalPositiveFiniteNumber
|
|
150
155
|
} from "./chunk-U6VC4MU4.js";
|
|
151
|
-
import {
|
|
152
|
-
isRecord
|
|
153
|
-
} from "./chunk-KUG52IAP.js";
|
|
154
156
|
import {
|
|
155
157
|
normalizeServerOrigin
|
|
156
158
|
} from "./chunk-CF7PE763.js";
|
|
@@ -12200,8 +12202,208 @@ function summarizeToolArguments(toolName, rawArgs) {
|
|
|
12200
12202
|
);
|
|
12201
12203
|
}
|
|
12202
12204
|
|
|
12205
|
+
// packages/agent-runtime/progressGuard.ts
|
|
12206
|
+
var DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS = 5;
|
|
12207
|
+
var DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS = 8;
|
|
12208
|
+
function sortJsonKeys(obj) {
|
|
12209
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
12210
|
+
if (Array.isArray(obj)) return obj.map(sortJsonKeys);
|
|
12211
|
+
const sorted = {};
|
|
12212
|
+
for (const key of Object.keys(obj).sort()) {
|
|
12213
|
+
sorted[key] = sortJsonKeys(obj[key]);
|
|
12214
|
+
}
|
|
12215
|
+
return sorted;
|
|
12216
|
+
}
|
|
12217
|
+
function normalizeToolArguments(rawArgs) {
|
|
12218
|
+
if (typeof rawArgs !== "string") {
|
|
12219
|
+
try {
|
|
12220
|
+
return JSON.stringify(sortJsonKeys(rawArgs ?? ""));
|
|
12221
|
+
} catch {
|
|
12222
|
+
return String(rawArgs ?? "");
|
|
12223
|
+
}
|
|
12224
|
+
}
|
|
12225
|
+
const trimmed = rawArgs.trim();
|
|
12226
|
+
if (!trimmed) return "";
|
|
12227
|
+
try {
|
|
12228
|
+
const parsed = JSON.parse(trimmed);
|
|
12229
|
+
return JSON.stringify(sortJsonKeys(parsed));
|
|
12230
|
+
} catch {
|
|
12231
|
+
return trimmed;
|
|
12232
|
+
}
|
|
12233
|
+
}
|
|
12234
|
+
function extractNormalizedContentText(content) {
|
|
12235
|
+
if (typeof content === "string") return content.trim();
|
|
12236
|
+
if (!Array.isArray(content)) return "";
|
|
12237
|
+
return content.map((part) => {
|
|
12238
|
+
if (part?.type === "text") return String(part.text ?? "").trim();
|
|
12239
|
+
if (part?.type === "image_url") return `[img:${part.image_url?.url ?? ""}]`;
|
|
12240
|
+
return "";
|
|
12241
|
+
}).filter(Boolean).join("\n");
|
|
12242
|
+
}
|
|
12243
|
+
function buildToolCallsSignature(toolCalls) {
|
|
12244
|
+
if (!toolCalls || toolCalls.length === 0) return "";
|
|
12245
|
+
return toolCalls.map(
|
|
12246
|
+
(tc) => `${tc.function?.name ?? ""}:${normalizeToolArguments(tc.function?.arguments)}`
|
|
12247
|
+
).join(";;");
|
|
12248
|
+
}
|
|
12249
|
+
function buildAssistantActionFingerprint(result4) {
|
|
12250
|
+
const content = extractNormalizedContentText(result4.content);
|
|
12251
|
+
const reasoning = typeof result4.reasoning_content === "string" ? result4.reasoning_content.trim() : "";
|
|
12252
|
+
let toolCallsSig = buildToolCallsSignature(result4.tool_calls);
|
|
12253
|
+
let hasToolCalls = Array.isArray(result4.tool_calls) && result4.tool_calls.length > 0;
|
|
12254
|
+
if (!toolCallsSig && Array.isArray(result4.output) && result4.output.length > 0) {
|
|
12255
|
+
const blocksToolCalls = result4.output.filter(
|
|
12256
|
+
(b) => b.type === "toolCall"
|
|
12257
|
+
).map((b) => b.toolCall);
|
|
12258
|
+
if (blocksToolCalls.length > 0) {
|
|
12259
|
+
toolCallsSig = buildToolCallsSignature(blocksToolCalls);
|
|
12260
|
+
hasToolCalls = true;
|
|
12261
|
+
}
|
|
12262
|
+
}
|
|
12263
|
+
const hasNonEmptyText = content.length > 0 || reasoning.length > 0;
|
|
12264
|
+
const fingerprint = `${content}##${reasoning}##${toolCallsSig}`;
|
|
12265
|
+
return {
|
|
12266
|
+
fingerprint,
|
|
12267
|
+
hasNonEmptyText,
|
|
12268
|
+
hasToolCalls,
|
|
12269
|
+
toolCallsSignature: toolCallsSig
|
|
12270
|
+
};
|
|
12271
|
+
}
|
|
12272
|
+
function buildToolResultsSignature(toolExecutions) {
|
|
12273
|
+
if (toolExecutions.length === 0) return "";
|
|
12274
|
+
return toolExecutions.map((exec) => {
|
|
12275
|
+
const contentStr = typeof exec.content === "string" ? exec.content.trim() : "";
|
|
12276
|
+
const metaStr = exec.metadata ? JSON.stringify(sortJsonKeys(exec.metadata)) : "";
|
|
12277
|
+
return `${exec.toolName}:${contentStr}:${metaStr}`;
|
|
12278
|
+
}).join(";;");
|
|
12279
|
+
}
|
|
12280
|
+
function resolveProgressGuardConfig(options, env = typeof process !== "undefined" ? process.env : {}) {
|
|
12281
|
+
const envDisabled = env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "true" || env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "1";
|
|
12282
|
+
const disabled = options?.disabled ?? envDisabled ?? false;
|
|
12283
|
+
const parsePositiveInt = (val, fallback) => {
|
|
12284
|
+
if (typeof val === "number" && Number.isFinite(val) && val >= 1) {
|
|
12285
|
+
return Math.floor(val);
|
|
12286
|
+
}
|
|
12287
|
+
if (typeof val === "string") {
|
|
12288
|
+
const parsed = parseInt(val, 10);
|
|
12289
|
+
if (Number.isFinite(parsed) && parsed >= 1) {
|
|
12290
|
+
return parsed;
|
|
12291
|
+
}
|
|
12292
|
+
}
|
|
12293
|
+
return fallback;
|
|
12294
|
+
};
|
|
12295
|
+
const maxConsecutiveIdenticalRounds = parsePositiveInt(
|
|
12296
|
+
options?.maxConsecutiveIdenticalRounds ?? env.NOLO_LOOP_MAX_IDENTICAL_ROUNDS,
|
|
12297
|
+
DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS
|
|
12298
|
+
);
|
|
12299
|
+
const maxConsecutiveStagnantToolRounds = parsePositiveInt(
|
|
12300
|
+
options?.maxConsecutiveStagnantToolRounds ?? env.NOLO_LOOP_MAX_STAGNANT_TOOL_ROUNDS,
|
|
12301
|
+
DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS
|
|
12302
|
+
);
|
|
12303
|
+
return {
|
|
12304
|
+
disabled,
|
|
12305
|
+
maxConsecutiveIdenticalRounds,
|
|
12306
|
+
maxConsecutiveStagnantToolRounds
|
|
12307
|
+
};
|
|
12308
|
+
}
|
|
12309
|
+
var LocalLoopProgressGuard = class {
|
|
12310
|
+
config;
|
|
12311
|
+
lastAssistantFingerprint = null;
|
|
12312
|
+
lastAssistantHasNonEmptyText = false;
|
|
12313
|
+
consecutiveIdenticalCount = 0;
|
|
12314
|
+
lastToolCallsSignature = null;
|
|
12315
|
+
lastToolResultsSignature = null;
|
|
12316
|
+
consecutiveStagnantToolCount = 0;
|
|
12317
|
+
constructor(config, env) {
|
|
12318
|
+
this.config = resolveProgressGuardConfig(config, env);
|
|
12319
|
+
}
|
|
12320
|
+
/**
|
|
12321
|
+
* 在 LLM 返回 assistant 响应后调用。
|
|
12322
|
+
* 仅在纯文本/无工具调用且实质文本相同达到阈值时直接熔断;
|
|
12323
|
+
* 若存在工具调用,则不在此处熔断,留待工具执行后结合工具结果综合判定。
|
|
12324
|
+
*/
|
|
12325
|
+
observeAssistantResponse(result4) {
|
|
12326
|
+
if (this.config.disabled) return { action: "continue" };
|
|
12327
|
+
const { fingerprint, hasNonEmptyText, hasToolCalls } = buildAssistantActionFingerprint(result4);
|
|
12328
|
+
if (this.lastAssistantFingerprint !== null && this.lastAssistantFingerprint === fingerprint) {
|
|
12329
|
+
this.consecutiveIdenticalCount += 1;
|
|
12330
|
+
if (!hasToolCalls && hasNonEmptyText && this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
|
|
12331
|
+
return {
|
|
12332
|
+
action: "stall",
|
|
12333
|
+
reason: "repetition_loop",
|
|
12334
|
+
detail: `Consecutive identical text-only assistant response for ${this.consecutiveIdenticalCount} rounds.`,
|
|
12335
|
+
consecutiveRounds: this.consecutiveIdenticalCount
|
|
12336
|
+
};
|
|
12337
|
+
}
|
|
12338
|
+
} else {
|
|
12339
|
+
this.lastAssistantFingerprint = fingerprint;
|
|
12340
|
+
this.lastAssistantHasNonEmptyText = hasNonEmptyText;
|
|
12341
|
+
this.consecutiveIdenticalCount = 1;
|
|
12342
|
+
}
|
|
12343
|
+
return { action: "continue" };
|
|
12344
|
+
}
|
|
12345
|
+
/**
|
|
12346
|
+
* 在本轮所有工具执行完毕后调用,检查是否陷入停滞死循环。
|
|
12347
|
+
* 只有当工具返回内容与元数据完全无变化时才计入无进展 streak;
|
|
12348
|
+
* 一旦工具结果发生变化(如合法轮询状态推进),立即重置 identical streak,确保绝不误杀正常长任务。
|
|
12349
|
+
*/
|
|
12350
|
+
observeToolExecution(toolCalls, toolResults) {
|
|
12351
|
+
if (this.config.disabled) return { action: "continue" };
|
|
12352
|
+
if (!toolCalls || toolCalls.length === 0) return { action: "continue" };
|
|
12353
|
+
const toolCallsSig = buildToolCallsSignature(toolCalls);
|
|
12354
|
+
const toolResultsSig = buildToolResultsSignature(toolResults);
|
|
12355
|
+
const toolCallsUnchanged = this.lastToolCallsSignature !== null && this.lastToolCallsSignature === toolCallsSig;
|
|
12356
|
+
const toolResultsUnchanged = this.lastToolResultsSignature !== null && this.lastToolResultsSignature === toolResultsSig;
|
|
12357
|
+
if (toolCallsUnchanged && toolResultsUnchanged) {
|
|
12358
|
+
this.consecutiveStagnantToolCount += 1;
|
|
12359
|
+
if (this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
|
|
12360
|
+
return {
|
|
12361
|
+
action: "stall",
|
|
12362
|
+
reason: "repetition_loop",
|
|
12363
|
+
detail: `Consecutive identical assistant response with unchanged tool results for ${this.consecutiveIdenticalCount} rounds.`,
|
|
12364
|
+
consecutiveRounds: this.consecutiveIdenticalCount
|
|
12365
|
+
};
|
|
12366
|
+
}
|
|
12367
|
+
if (this.consecutiveStagnantToolCount >= this.config.maxConsecutiveStagnantToolRounds) {
|
|
12368
|
+
return {
|
|
12369
|
+
action: "stall",
|
|
12370
|
+
reason: "stagnant_tool_calls",
|
|
12371
|
+
detail: `Consecutive stagnant tool calls with unchanged results for ${this.consecutiveStagnantToolCount} rounds.`,
|
|
12372
|
+
consecutiveRounds: this.consecutiveStagnantToolCount
|
|
12373
|
+
};
|
|
12374
|
+
}
|
|
12375
|
+
} else {
|
|
12376
|
+
this.lastToolCallsSignature = toolCallsSig;
|
|
12377
|
+
this.lastToolResultsSignature = toolResultsSig;
|
|
12378
|
+
this.consecutiveStagnantToolCount = 1;
|
|
12379
|
+
if (!toolResultsUnchanged) {
|
|
12380
|
+
this.consecutiveIdenticalCount = 1;
|
|
12381
|
+
}
|
|
12382
|
+
}
|
|
12383
|
+
return { action: "continue" };
|
|
12384
|
+
}
|
|
12385
|
+
};
|
|
12386
|
+
function createLocalLoopProgressGuard(config, env) {
|
|
12387
|
+
return new LocalLoopProgressGuard(config, env);
|
|
12388
|
+
}
|
|
12389
|
+
|
|
12390
|
+
// packages/agent-runtime/toolArgumentsFingerprint.ts
|
|
12391
|
+
var hashFingerprintInput = (value) => {
|
|
12392
|
+
let hash2 = 2166136261;
|
|
12393
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
12394
|
+
hash2 ^= value.charCodeAt(index);
|
|
12395
|
+
hash2 = Math.imul(hash2, 16777619);
|
|
12396
|
+
}
|
|
12397
|
+
return (hash2 >>> 0).toString(16).padStart(8, "0");
|
|
12398
|
+
};
|
|
12399
|
+
function buildToolArgumentsFingerprint(rawArguments) {
|
|
12400
|
+
if (rawArguments === void 0 || rawArguments === null) return void 0;
|
|
12401
|
+
const normalized = normalizeToolArguments(rawArguments);
|
|
12402
|
+
return hashFingerprintInput(normalized);
|
|
12403
|
+
}
|
|
12404
|
+
|
|
12203
12405
|
// packages/agent-runtime/leafFinalHandoff.ts
|
|
12204
|
-
var LEAF_FINAL_HANDOFF_INSTRUCTIONS = `Leaf subtask final: return only the result, blockers/findings, and minimal evidence the parent needs. Do not narrate your process or restate the task. Keep success minimal (a one-line result is enough); on failure include the blocker, severity when relevant, and an evidence reference (file:line, test command, commit, artifact, or run/dialog). If the task explicitly requires a long-form deliverable (document, translation, dataset, code, or other artifact), provide that deliverable in full and keep only the handoff around it concise.`;
|
|
12406
|
+
var LEAF_FINAL_HANDOFF_INSTRUCTIONS = `Leaf subtask final: return only the result, blockers/findings, and minimal evidence the parent needs. Do not narrate your process or restate the task. Keep success minimal (a one-line result is enough); on failure include the blocker, severity when relevant, and an evidence reference (file:line, test command, commit, artifact, or run/dialog). If the task explicitly requires a long-form deliverable (document, translation, dataset, code, or other artifact), provide that deliverable in full and keep only the handoff around it concise. During execution, follow the brief as given: only when new evidence would materially change the goal, risk, irreversibility, or DoD should you surface it as a blocker/finding in the handoff \u2014 do not silently expand scope or re-litigate the settled direction.`;
|
|
12205
12407
|
|
|
12206
12408
|
// packages/agent-runtime/contextBlockScope.ts
|
|
12207
12409
|
var isContextBlockScope = (value) => {
|
|
@@ -12556,218 +12758,33 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
12556
12758
|
}
|
|
12557
12759
|
}
|
|
12558
12760
|
|
|
12559
|
-
// packages/agent-runtime/
|
|
12560
|
-
var
|
|
12561
|
-
var
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
|
|
12761
|
+
// packages/agent-runtime/localLoop.ts
|
|
12762
|
+
var LOOP_TIMING_ENABLED = typeof process !== "undefined" && process.env?.NOLO_LOOP_TIMING === "1";
|
|
12763
|
+
var LOOP_TIMING_FILE = typeof process !== "undefined" ? process.env?.NOLO_LOOP_TIMING_FILE : void 0;
|
|
12764
|
+
var loopTimingRows = [];
|
|
12765
|
+
var loopTimingLastMark;
|
|
12766
|
+
function loopTimingMark(phase, round) {
|
|
12767
|
+
if (!LOOP_TIMING_ENABLED) return;
|
|
12768
|
+
const now = performance.now();
|
|
12769
|
+
if (loopTimingLastMark !== void 0) {
|
|
12770
|
+
loopTimingRows.push({ phase, round, durationMs: now - loopTimingLastMark });
|
|
12568
12771
|
}
|
|
12569
|
-
|
|
12772
|
+
loopTimingLastMark = now;
|
|
12570
12773
|
}
|
|
12571
|
-
function
|
|
12572
|
-
if (
|
|
12774
|
+
async function loopTimingFlush() {
|
|
12775
|
+
if (!LOOP_TIMING_ENABLED) return;
|
|
12776
|
+
const lines = loopTimingRows.map((row) => JSON.stringify(row)).join("\n");
|
|
12777
|
+
loopTimingRows = [];
|
|
12778
|
+
loopTimingLastMark = void 0;
|
|
12779
|
+
if (!lines) return;
|
|
12780
|
+
if (LOOP_TIMING_FILE) {
|
|
12573
12781
|
try {
|
|
12574
|
-
|
|
12782
|
+
const { appendFileSync } = await import("node:fs");
|
|
12783
|
+
appendFileSync(LOOP_TIMING_FILE, lines + "\n");
|
|
12575
12784
|
} catch {
|
|
12576
|
-
return String(rawArgs ?? "");
|
|
12577
12785
|
}
|
|
12578
|
-
}
|
|
12579
|
-
|
|
12580
|
-
if (!trimmed) return "";
|
|
12581
|
-
try {
|
|
12582
|
-
const parsed = JSON.parse(trimmed);
|
|
12583
|
-
return JSON.stringify(sortJsonKeys(parsed));
|
|
12584
|
-
} catch {
|
|
12585
|
-
return trimmed;
|
|
12586
|
-
}
|
|
12587
|
-
}
|
|
12588
|
-
function extractNormalizedContentText(content) {
|
|
12589
|
-
if (typeof content === "string") return content.trim();
|
|
12590
|
-
if (!Array.isArray(content)) return "";
|
|
12591
|
-
return content.map((part) => {
|
|
12592
|
-
if (part?.type === "text") return String(part.text ?? "").trim();
|
|
12593
|
-
if (part?.type === "image_url") return `[img:${part.image_url?.url ?? ""}]`;
|
|
12594
|
-
return "";
|
|
12595
|
-
}).filter(Boolean).join("\n");
|
|
12596
|
-
}
|
|
12597
|
-
function buildToolCallsSignature(toolCalls) {
|
|
12598
|
-
if (!toolCalls || toolCalls.length === 0) return "";
|
|
12599
|
-
return toolCalls.map(
|
|
12600
|
-
(tc) => `${tc.function?.name ?? ""}:${normalizeToolArguments(tc.function?.arguments)}`
|
|
12601
|
-
).join(";;");
|
|
12602
|
-
}
|
|
12603
|
-
function buildAssistantActionFingerprint(result4) {
|
|
12604
|
-
const content = extractNormalizedContentText(result4.content);
|
|
12605
|
-
const reasoning = typeof result4.reasoning_content === "string" ? result4.reasoning_content.trim() : "";
|
|
12606
|
-
let toolCallsSig = buildToolCallsSignature(result4.tool_calls);
|
|
12607
|
-
let hasToolCalls = Array.isArray(result4.tool_calls) && result4.tool_calls.length > 0;
|
|
12608
|
-
if (!toolCallsSig && Array.isArray(result4.output) && result4.output.length > 0) {
|
|
12609
|
-
const blocksToolCalls = result4.output.filter(
|
|
12610
|
-
(b) => b.type === "toolCall"
|
|
12611
|
-
).map((b) => b.toolCall);
|
|
12612
|
-
if (blocksToolCalls.length > 0) {
|
|
12613
|
-
toolCallsSig = buildToolCallsSignature(blocksToolCalls);
|
|
12614
|
-
hasToolCalls = true;
|
|
12615
|
-
}
|
|
12616
|
-
}
|
|
12617
|
-
const hasNonEmptyText = content.length > 0 || reasoning.length > 0;
|
|
12618
|
-
const fingerprint = `${content}##${reasoning}##${toolCallsSig}`;
|
|
12619
|
-
return {
|
|
12620
|
-
fingerprint,
|
|
12621
|
-
hasNonEmptyText,
|
|
12622
|
-
hasToolCalls,
|
|
12623
|
-
toolCallsSignature: toolCallsSig
|
|
12624
|
-
};
|
|
12625
|
-
}
|
|
12626
|
-
function buildToolResultsSignature(toolExecutions) {
|
|
12627
|
-
if (toolExecutions.length === 0) return "";
|
|
12628
|
-
return toolExecutions.map((exec) => {
|
|
12629
|
-
const contentStr = typeof exec.content === "string" ? exec.content.trim() : "";
|
|
12630
|
-
const metaStr = exec.metadata ? JSON.stringify(sortJsonKeys(exec.metadata)) : "";
|
|
12631
|
-
return `${exec.toolName}:${contentStr}:${metaStr}`;
|
|
12632
|
-
}).join(";;");
|
|
12633
|
-
}
|
|
12634
|
-
function resolveProgressGuardConfig(options, env = typeof process !== "undefined" ? process.env : {}) {
|
|
12635
|
-
const envDisabled = env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "true" || env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "1";
|
|
12636
|
-
const disabled = options?.disabled ?? envDisabled ?? false;
|
|
12637
|
-
const parsePositiveInt = (val, fallback) => {
|
|
12638
|
-
if (typeof val === "number" && Number.isFinite(val) && val >= 1) {
|
|
12639
|
-
return Math.floor(val);
|
|
12640
|
-
}
|
|
12641
|
-
if (typeof val === "string") {
|
|
12642
|
-
const parsed = parseInt(val, 10);
|
|
12643
|
-
if (Number.isFinite(parsed) && parsed >= 1) {
|
|
12644
|
-
return parsed;
|
|
12645
|
-
}
|
|
12646
|
-
}
|
|
12647
|
-
return fallback;
|
|
12648
|
-
};
|
|
12649
|
-
const maxConsecutiveIdenticalRounds = parsePositiveInt(
|
|
12650
|
-
options?.maxConsecutiveIdenticalRounds ?? env.NOLO_LOOP_MAX_IDENTICAL_ROUNDS,
|
|
12651
|
-
DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS
|
|
12652
|
-
);
|
|
12653
|
-
const maxConsecutiveStagnantToolRounds = parsePositiveInt(
|
|
12654
|
-
options?.maxConsecutiveStagnantToolRounds ?? env.NOLO_LOOP_MAX_STAGNANT_TOOL_ROUNDS,
|
|
12655
|
-
DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS
|
|
12656
|
-
);
|
|
12657
|
-
return {
|
|
12658
|
-
disabled,
|
|
12659
|
-
maxConsecutiveIdenticalRounds,
|
|
12660
|
-
maxConsecutiveStagnantToolRounds
|
|
12661
|
-
};
|
|
12662
|
-
}
|
|
12663
|
-
var LocalLoopProgressGuard = class {
|
|
12664
|
-
config;
|
|
12665
|
-
lastAssistantFingerprint = null;
|
|
12666
|
-
lastAssistantHasNonEmptyText = false;
|
|
12667
|
-
consecutiveIdenticalCount = 0;
|
|
12668
|
-
lastToolCallsSignature = null;
|
|
12669
|
-
lastToolResultsSignature = null;
|
|
12670
|
-
consecutiveStagnantToolCount = 0;
|
|
12671
|
-
constructor(config, env) {
|
|
12672
|
-
this.config = resolveProgressGuardConfig(config, env);
|
|
12673
|
-
}
|
|
12674
|
-
/**
|
|
12675
|
-
* 在 LLM 返回 assistant 响应后调用。
|
|
12676
|
-
* 仅在纯文本/无工具调用且实质文本相同达到阈值时直接熔断;
|
|
12677
|
-
* 若存在工具调用,则不在此处熔断,留待工具执行后结合工具结果综合判定。
|
|
12678
|
-
*/
|
|
12679
|
-
observeAssistantResponse(result4) {
|
|
12680
|
-
if (this.config.disabled) return { action: "continue" };
|
|
12681
|
-
const { fingerprint, hasNonEmptyText, hasToolCalls } = buildAssistantActionFingerprint(result4);
|
|
12682
|
-
if (this.lastAssistantFingerprint !== null && this.lastAssistantFingerprint === fingerprint) {
|
|
12683
|
-
this.consecutiveIdenticalCount += 1;
|
|
12684
|
-
if (!hasToolCalls && hasNonEmptyText && this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
|
|
12685
|
-
return {
|
|
12686
|
-
action: "stall",
|
|
12687
|
-
reason: "repetition_loop",
|
|
12688
|
-
detail: `Consecutive identical text-only assistant response for ${this.consecutiveIdenticalCount} rounds.`,
|
|
12689
|
-
consecutiveRounds: this.consecutiveIdenticalCount
|
|
12690
|
-
};
|
|
12691
|
-
}
|
|
12692
|
-
} else {
|
|
12693
|
-
this.lastAssistantFingerprint = fingerprint;
|
|
12694
|
-
this.lastAssistantHasNonEmptyText = hasNonEmptyText;
|
|
12695
|
-
this.consecutiveIdenticalCount = 1;
|
|
12696
|
-
}
|
|
12697
|
-
return { action: "continue" };
|
|
12698
|
-
}
|
|
12699
|
-
/**
|
|
12700
|
-
* 在本轮所有工具执行完毕后调用,检查是否陷入停滞死循环。
|
|
12701
|
-
* 只有当工具返回内容与元数据完全无变化时才计入无进展 streak;
|
|
12702
|
-
* 一旦工具结果发生变化(如合法轮询状态推进),立即重置 identical streak,确保绝不误杀正常长任务。
|
|
12703
|
-
*/
|
|
12704
|
-
observeToolExecution(toolCalls, toolResults) {
|
|
12705
|
-
if (this.config.disabled) return { action: "continue" };
|
|
12706
|
-
if (!toolCalls || toolCalls.length === 0) return { action: "continue" };
|
|
12707
|
-
const toolCallsSig = buildToolCallsSignature(toolCalls);
|
|
12708
|
-
const toolResultsSig = buildToolResultsSignature(toolResults);
|
|
12709
|
-
const toolCallsUnchanged = this.lastToolCallsSignature !== null && this.lastToolCallsSignature === toolCallsSig;
|
|
12710
|
-
const toolResultsUnchanged = this.lastToolResultsSignature !== null && this.lastToolResultsSignature === toolResultsSig;
|
|
12711
|
-
if (toolCallsUnchanged && toolResultsUnchanged) {
|
|
12712
|
-
this.consecutiveStagnantToolCount += 1;
|
|
12713
|
-
if (this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
|
|
12714
|
-
return {
|
|
12715
|
-
action: "stall",
|
|
12716
|
-
reason: "repetition_loop",
|
|
12717
|
-
detail: `Consecutive identical assistant response with unchanged tool results for ${this.consecutiveIdenticalCount} rounds.`,
|
|
12718
|
-
consecutiveRounds: this.consecutiveIdenticalCount
|
|
12719
|
-
};
|
|
12720
|
-
}
|
|
12721
|
-
if (this.consecutiveStagnantToolCount >= this.config.maxConsecutiveStagnantToolRounds) {
|
|
12722
|
-
return {
|
|
12723
|
-
action: "stall",
|
|
12724
|
-
reason: "stagnant_tool_calls",
|
|
12725
|
-
detail: `Consecutive stagnant tool calls with unchanged results for ${this.consecutiveStagnantToolCount} rounds.`,
|
|
12726
|
-
consecutiveRounds: this.consecutiveStagnantToolCount
|
|
12727
|
-
};
|
|
12728
|
-
}
|
|
12729
|
-
} else {
|
|
12730
|
-
this.lastToolCallsSignature = toolCallsSig;
|
|
12731
|
-
this.lastToolResultsSignature = toolResultsSig;
|
|
12732
|
-
this.consecutiveStagnantToolCount = 1;
|
|
12733
|
-
if (!toolResultsUnchanged) {
|
|
12734
|
-
this.consecutiveIdenticalCount = 1;
|
|
12735
|
-
}
|
|
12736
|
-
}
|
|
12737
|
-
return { action: "continue" };
|
|
12738
|
-
}
|
|
12739
|
-
};
|
|
12740
|
-
function createLocalLoopProgressGuard(config, env) {
|
|
12741
|
-
return new LocalLoopProgressGuard(config, env);
|
|
12742
|
-
}
|
|
12743
|
-
|
|
12744
|
-
// packages/agent-runtime/localLoop.ts
|
|
12745
|
-
var LOOP_TIMING_ENABLED = typeof process !== "undefined" && process.env?.NOLO_LOOP_TIMING === "1";
|
|
12746
|
-
var LOOP_TIMING_FILE = typeof process !== "undefined" ? process.env?.NOLO_LOOP_TIMING_FILE : void 0;
|
|
12747
|
-
var loopTimingRows = [];
|
|
12748
|
-
var loopTimingLastMark;
|
|
12749
|
-
function loopTimingMark(phase, round) {
|
|
12750
|
-
if (!LOOP_TIMING_ENABLED) return;
|
|
12751
|
-
const now = performance.now();
|
|
12752
|
-
if (loopTimingLastMark !== void 0) {
|
|
12753
|
-
loopTimingRows.push({ phase, round, durationMs: now - loopTimingLastMark });
|
|
12754
|
-
}
|
|
12755
|
-
loopTimingLastMark = now;
|
|
12756
|
-
}
|
|
12757
|
-
async function loopTimingFlush() {
|
|
12758
|
-
if (!LOOP_TIMING_ENABLED) return;
|
|
12759
|
-
const lines = loopTimingRows.map((row) => JSON.stringify(row)).join("\n");
|
|
12760
|
-
loopTimingRows = [];
|
|
12761
|
-
loopTimingLastMark = void 0;
|
|
12762
|
-
if (!lines) return;
|
|
12763
|
-
if (LOOP_TIMING_FILE) {
|
|
12764
|
-
try {
|
|
12765
|
-
const { appendFileSync } = await import("node:fs");
|
|
12766
|
-
appendFileSync(LOOP_TIMING_FILE, lines + "\n");
|
|
12767
|
-
} catch {
|
|
12768
|
-
}
|
|
12769
|
-
} else {
|
|
12770
|
-
process.stderr.write(lines + "\n");
|
|
12786
|
+
} else {
|
|
12787
|
+
process.stderr.write(lines + "\n");
|
|
12771
12788
|
}
|
|
12772
12789
|
}
|
|
12773
12790
|
var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
|
|
@@ -13046,10 +13063,10 @@ var TOOL_METADATA_KEYS = [
|
|
|
13046
13063
|
"pasteId",
|
|
13047
13064
|
"source"
|
|
13048
13065
|
];
|
|
13049
|
-
function trimHistoryToContextBudget(history, model) {
|
|
13066
|
+
function trimHistoryToContextBudget(history, model, contextWindowOverride) {
|
|
13050
13067
|
if (history.length === 0) return { history, droppedCount: 0 };
|
|
13051
13068
|
const { rawMessageBudget } = planContextUsage({
|
|
13052
|
-
contextWindow: getModelContextWindow(model ?? ""),
|
|
13069
|
+
contextWindow: contextWindowOverride ?? getModelContextWindow(model ?? ""),
|
|
13053
13070
|
summaryTokens: 0,
|
|
13054
13071
|
// localLoop 没有 web 端的负载分档器;medium 是中性默认值,
|
|
13055
13072
|
// 不为了省几个 token 在这里复制一份分类逻辑。
|
|
@@ -13540,7 +13557,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13540
13557
|
}
|
|
13541
13558
|
return resolvedProvider;
|
|
13542
13559
|
};
|
|
13543
|
-
const contextWindow =
|
|
13560
|
+
const contextWindow = resolveAgentContextWindow(agentConfig);
|
|
13544
13561
|
const compressionTriggerRatio = resolveCompressionTriggerRatio(contextWindow);
|
|
13545
13562
|
let realContextUsagePercent;
|
|
13546
13563
|
if (input.continueDialogId && typeof input.adapter.loadLastContextUsage === "function") {
|
|
@@ -13582,6 +13599,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13582
13599
|
history,
|
|
13583
13600
|
model: agentConfig.model,
|
|
13584
13601
|
resolveProvider: resolveProviderOnce,
|
|
13602
|
+
contextWindow,
|
|
13585
13603
|
realContextUsagePercent
|
|
13586
13604
|
});
|
|
13587
13605
|
history = compacted.history;
|
|
@@ -13591,7 +13609,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13591
13609
|
console.warn("[localLoop] auto-compaction unexpected error:", error);
|
|
13592
13610
|
}
|
|
13593
13611
|
loopTimingMark("maybeAutoCompactLocalHistory", 0);
|
|
13594
|
-
const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model);
|
|
13612
|
+
const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model, contextWindow);
|
|
13595
13613
|
if (trimmedHistory.droppedCount > 0) {
|
|
13596
13614
|
history = trimmedHistory.history;
|
|
13597
13615
|
}
|
|
@@ -13678,6 +13696,7 @@ async function runLocalAgentTurn(input) {
|
|
|
13678
13696
|
],
|
|
13679
13697
|
model: agentConfig.model,
|
|
13680
13698
|
resolveProvider: resolveProviderOnce,
|
|
13699
|
+
contextWindow,
|
|
13681
13700
|
realContextUsagePercent: ratio
|
|
13682
13701
|
});
|
|
13683
13702
|
if (compacted.usage) {
|
|
@@ -13946,6 +13965,7 @@ ${reasoningTailLog}
|
|
|
13946
13965
|
const startedAt = Date.now();
|
|
13947
13966
|
loopTimingMark("toolCallStart", round);
|
|
13948
13967
|
const argumentsPreview = summarizeToolArguments(toolName, toolCall.function.arguments);
|
|
13968
|
+
const argumentsFingerprint = buildToolArgumentsFingerprint(toolCall.function.arguments);
|
|
13949
13969
|
emitLoopEvent(
|
|
13950
13970
|
observationBoundary,
|
|
13951
13971
|
{
|
|
@@ -13954,7 +13974,8 @@ ${reasoningTailLog}
|
|
|
13954
13974
|
toolCallId: toolCall.id,
|
|
13955
13975
|
toolName,
|
|
13956
13976
|
atMs: startedAt,
|
|
13957
|
-
...argumentsPreview ? { argumentsPreview } : {}
|
|
13977
|
+
...argumentsPreview ? { argumentsPreview } : {},
|
|
13978
|
+
...argumentsFingerprint ? { argumentsFingerprint } : {}
|
|
13958
13979
|
},
|
|
13959
13980
|
{
|
|
13960
13981
|
type: "tool-call",
|
|
@@ -15568,13 +15589,13 @@ var DEFAULT_LOCAL_TOOLS = /* @__PURE__ */ new Set([
|
|
|
15568
15589
|
"execShell",
|
|
15569
15590
|
"launchProcess",
|
|
15570
15591
|
"listProcesses",
|
|
15571
|
-
// ProcessTask follow-up tools
|
|
15572
|
-
//
|
|
15573
|
-
//
|
|
15592
|
+
// ProcessTask follow-up tools. Same tier as listProcesses: they observe/stop
|
|
15593
|
+
// tasks the agent itself already spawned, so their blast radius is strictly
|
|
15594
|
+
// narrower than launchProcess (which is default-enabled). Model-facing
|
|
15595
|
+
// follow-ups are taskWait/taskStop only — lifecycle history (taskLogs) stays
|
|
15596
|
+
// runtime-internal.
|
|
15574
15597
|
"taskWait",
|
|
15575
|
-
"taskLogs",
|
|
15576
15598
|
"taskStop",
|
|
15577
|
-
"tasks",
|
|
15578
15599
|
// Scheduling tools: forking/observing sub-agents is a declared capability
|
|
15579
15600
|
// of capable agents, and the blast radius is strictly narrower than
|
|
15580
15601
|
// execShell (already default-enabled). Requiring an env allowlist for these
|
|
@@ -16210,6 +16231,24 @@ var ProcessTaskEventLog = class {
|
|
|
16210
16231
|
};
|
|
16211
16232
|
|
|
16212
16233
|
// packages/agent-runtime/processRegistry.ts
|
|
16234
|
+
function toProcessTaskView(record) {
|
|
16235
|
+
const capsule = record.resultCapsule;
|
|
16236
|
+
return {
|
|
16237
|
+
taskId: record.taskId,
|
|
16238
|
+
pid: record.pid,
|
|
16239
|
+
pgid: record.pgid,
|
|
16240
|
+
command: record.command,
|
|
16241
|
+
label: record.label,
|
|
16242
|
+
startedAt: record.startedAt,
|
|
16243
|
+
status: record.status,
|
|
16244
|
+
...record.exitCode !== void 0 ? { exitCode: record.exitCode } : {},
|
|
16245
|
+
persist: record.persist,
|
|
16246
|
+
promoted: record.promoted,
|
|
16247
|
+
transient: record.transient,
|
|
16248
|
+
...capsule?.durationMs !== void 0 ? { durationMs: capsule.durationMs } : {},
|
|
16249
|
+
...capsule?.spill ? { outputRef: capsule.spill.displayPath } : {}
|
|
16250
|
+
};
|
|
16251
|
+
}
|
|
16213
16252
|
var taskIdCounter = 0;
|
|
16214
16253
|
function mintTaskId(pid) {
|
|
16215
16254
|
taskIdCounter += 1;
|
|
@@ -16265,7 +16304,7 @@ var ProcessRegistry = class {
|
|
|
16265
16304
|
startedAt: Date.now(),
|
|
16266
16305
|
status: "running",
|
|
16267
16306
|
persist: proc.persist ?? false,
|
|
16268
|
-
promoted: false,
|
|
16307
|
+
promoted: proc.promoted ?? false,
|
|
16269
16308
|
transient: proc.transient ?? false,
|
|
16270
16309
|
owner: proc.owner ?? null
|
|
16271
16310
|
};
|
|
@@ -16362,7 +16401,8 @@ var ProcessRegistry = class {
|
|
|
16362
16401
|
pid,
|
|
16363
16402
|
label: item.label,
|
|
16364
16403
|
command: item.command,
|
|
16365
|
-
status: "stopped"
|
|
16404
|
+
status: "stopped",
|
|
16405
|
+
promoted: item.promoted
|
|
16366
16406
|
});
|
|
16367
16407
|
return true;
|
|
16368
16408
|
}
|
|
@@ -16391,15 +16431,17 @@ var ProcessRegistry = class {
|
|
|
16391
16431
|
pid: item.pid,
|
|
16392
16432
|
label: item.label,
|
|
16393
16433
|
command: item.command,
|
|
16394
|
-
status: "stopped"
|
|
16434
|
+
status: "stopped",
|
|
16435
|
+
promoted: item.promoted
|
|
16395
16436
|
});
|
|
16396
16437
|
}
|
|
16397
16438
|
}
|
|
16398
16439
|
}
|
|
16399
|
-
markExited(pid, exitCode) {
|
|
16440
|
+
markExited(pid, exitCode, resultCapsule) {
|
|
16400
16441
|
const item = this.processes.get(pid);
|
|
16401
16442
|
if (item && item.status === "running") {
|
|
16402
16443
|
item.exitCode = exitCode;
|
|
16444
|
+
if (resultCapsule) item.resultCapsule = resultCapsule;
|
|
16403
16445
|
item.status = exitCode === 0 ? "exited" : "failed";
|
|
16404
16446
|
this.eventLog.append({
|
|
16405
16447
|
taskId: item.taskId,
|
|
@@ -16413,7 +16455,9 @@ var ProcessRegistry = class {
|
|
|
16413
16455
|
label: item.label,
|
|
16414
16456
|
command: item.command,
|
|
16415
16457
|
status: item.status,
|
|
16416
|
-
exitCode
|
|
16458
|
+
exitCode,
|
|
16459
|
+
promoted: item.promoted,
|
|
16460
|
+
...item.resultCapsule ? { resultCapsule: item.resultCapsule } : {}
|
|
16417
16461
|
});
|
|
16418
16462
|
}
|
|
16419
16463
|
}
|
|
@@ -16476,6 +16520,62 @@ function readProcessOwner(runtimeContext) {
|
|
|
16476
16520
|
// packages/agent-runtime/workspaceShell.ts
|
|
16477
16521
|
import { resolve as resolve3 } from "node:path";
|
|
16478
16522
|
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
16523
|
+
|
|
16524
|
+
// packages/agent-runtime/processTaskResult.ts
|
|
16525
|
+
var PROCESS_RESULT_CAPSULE_TAIL_CHARS = 4e3;
|
|
16526
|
+
var PROCESS_RESULT_CAPSULE_SPILL_THRESHOLD_CHARS = 2e4;
|
|
16527
|
+
function tailText(value, maxChars) {
|
|
16528
|
+
if (value.length <= maxChars) return { text: value, truncated: false };
|
|
16529
|
+
return { text: value.slice(-maxChars), truncated: true };
|
|
16530
|
+
}
|
|
16531
|
+
function formatCapsuleStream(name, value) {
|
|
16532
|
+
return value.trim() ? `${name}:
|
|
16533
|
+
${value.replace(/\n+$/, "")}` : "";
|
|
16534
|
+
}
|
|
16535
|
+
function buildProcessTaskResultCapsule(args2) {
|
|
16536
|
+
const tailChars = args2.tailChars ?? PROCESS_RESULT_CAPSULE_TAIL_CHARS;
|
|
16537
|
+
const spillThresholdChars = args2.spillThresholdChars ?? PROCESS_RESULT_CAPSULE_SPILL_THRESHOLD_CHARS;
|
|
16538
|
+
const stdout = typeof args2.stdout === "string" ? args2.stdout : "";
|
|
16539
|
+
const stderr = typeof args2.stderr === "string" ? args2.stderr : "";
|
|
16540
|
+
const exitCode = args2.exitCode;
|
|
16541
|
+
const captureError = args2.captureError?.trim() || void 0;
|
|
16542
|
+
const durationMs = typeof args2.startedAt === "number" && Number.isFinite(args2.startedAt) ? Math.max(0, (args2.endedAt ?? Date.now()) - args2.startedAt) : void 0;
|
|
16543
|
+
const stdoutTail = tailText(stdout, tailChars);
|
|
16544
|
+
const stderrTail = tailText(stderr, tailChars);
|
|
16545
|
+
const inlineSize = stdout.length + stderr.length;
|
|
16546
|
+
const inlineTruncated = stdoutTail.truncated || stderrTail.truncated;
|
|
16547
|
+
const shouldSpill = inlineTruncated || inlineSize > spillThresholdChars;
|
|
16548
|
+
let spill;
|
|
16549
|
+
if (shouldSpill) {
|
|
16550
|
+
try {
|
|
16551
|
+
const result4 = spillToolOutput({
|
|
16552
|
+
content: [
|
|
16553
|
+
formatCapsuleStream("stdout", stdout),
|
|
16554
|
+
formatCapsuleStream("stderr", stderr)
|
|
16555
|
+
].filter(Boolean).join("\n\n"),
|
|
16556
|
+
toolName: "execShell",
|
|
16557
|
+
...args2.workspaceRoot !== void 0 ? { workspaceRoot: args2.workspaceRoot } : {}
|
|
16558
|
+
});
|
|
16559
|
+
spill = {
|
|
16560
|
+
displayPath: result4.displayPath,
|
|
16561
|
+
totalChars: result4.totalChars,
|
|
16562
|
+
totalLines: result4.totalLines
|
|
16563
|
+
};
|
|
16564
|
+
} catch {
|
|
16565
|
+
}
|
|
16566
|
+
}
|
|
16567
|
+
return {
|
|
16568
|
+
stdout: stdoutTail.text,
|
|
16569
|
+
stderr: stderrTail.text,
|
|
16570
|
+
exitCode,
|
|
16571
|
+
...durationMs !== void 0 ? { durationMs } : {},
|
|
16572
|
+
...captureError ? { captureError } : {},
|
|
16573
|
+
truncated: inlineTruncated || Boolean(captureError),
|
|
16574
|
+
...spill ? { spill } : {}
|
|
16575
|
+
};
|
|
16576
|
+
}
|
|
16577
|
+
|
|
16578
|
+
// packages/agent-runtime/workspaceShell.ts
|
|
16479
16579
|
var EXEC_SHELL_TIMEOUT_ENV = "NOLO_EXEC_SHELL_TIMEOUT_MS";
|
|
16480
16580
|
var EXEC_SHELL_DETACH_ENV = "NOLO_EXEC_SHELL_DETACH_MS";
|
|
16481
16581
|
var DEFAULT_EXEC_SHELL_DETACH_MS = 12e4;
|
|
@@ -16855,6 +16955,15 @@ ${stderr.trim()}`, "exitCode: 127"].filter(Boolean).join("\n\n"),
|
|
|
16855
16955
|
)
|
|
16856
16956
|
};
|
|
16857
16957
|
}
|
|
16958
|
+
function stdoutPromiseResult(promise3) {
|
|
16959
|
+
return promise3.then(
|
|
16960
|
+
(value) => ({ value }),
|
|
16961
|
+
(error) => ({
|
|
16962
|
+
value: "",
|
|
16963
|
+
error: error instanceof Error ? error.message : String(error)
|
|
16964
|
+
})
|
|
16965
|
+
);
|
|
16966
|
+
}
|
|
16858
16967
|
async function runWorkspaceCommand(args2) {
|
|
16859
16968
|
const timeoutMs = asOptionalPositiveFiniteNumber(args2.timeoutMs);
|
|
16860
16969
|
const detached = process.platform !== "win32";
|
|
@@ -16913,8 +17022,8 @@ async function runWorkspaceCommand(args2) {
|
|
|
16913
17022
|
process.removeListener("SIGINT", cleanupChildOnHostSignal);
|
|
16914
17023
|
};
|
|
16915
17024
|
exitPromise.then(detachSignalCleanup, detachSignalCleanup);
|
|
16916
|
-
const
|
|
16917
|
-
const
|
|
17025
|
+
const stdoutCapture = stdoutPromiseResult(readNodeStream(proc.stdout));
|
|
17026
|
+
const stderrCapture = stdoutPromiseResult(readNodeStream(proc.stderr));
|
|
16918
17027
|
const killChild = (signal) => {
|
|
16919
17028
|
if (detached && typeof proc.pid === "number") {
|
|
16920
17029
|
try {
|
|
@@ -17007,12 +17116,36 @@ async function runWorkspaceCommand(args2) {
|
|
|
17007
17116
|
pgid,
|
|
17008
17117
|
command: args2.command.join(" "),
|
|
17009
17118
|
label,
|
|
17119
|
+
promoted: true,
|
|
17010
17120
|
owner: args2.owner ?? null
|
|
17011
17121
|
});
|
|
17012
17122
|
const taskId = envelope.taskId;
|
|
17013
17123
|
proc.on("close", (code) => {
|
|
17014
17124
|
detachSignalCleanup();
|
|
17015
|
-
|
|
17125
|
+
const exitCode2 = code ?? 1;
|
|
17126
|
+
void (async () => {
|
|
17127
|
+
const [stdoutResult, stderrResult] = await Promise.all([
|
|
17128
|
+
stdoutCapture,
|
|
17129
|
+
stderrCapture
|
|
17130
|
+
]);
|
|
17131
|
+
const stdout2 = stdoutResult.value;
|
|
17132
|
+
const stderr2 = stderrResult.value;
|
|
17133
|
+
let capsule;
|
|
17134
|
+
try {
|
|
17135
|
+
capsule = buildProcessTaskResultCapsule({
|
|
17136
|
+
stdout: stdout2,
|
|
17137
|
+
stderr: stderr2,
|
|
17138
|
+
exitCode: exitCode2,
|
|
17139
|
+
// Duration is measured from the registry envelope's startedAt
|
|
17140
|
+
// (spawn moment), not from the detach moment.
|
|
17141
|
+
startedAt: registry2.get(pid)?.startedAt,
|
|
17142
|
+
workspaceRoot: args2.workspaceRoot,
|
|
17143
|
+
captureError: [stdoutResult.error, stderrResult.error].filter(Boolean).join("; ")
|
|
17144
|
+
});
|
|
17145
|
+
} catch {
|
|
17146
|
+
}
|
|
17147
|
+
registry2.markExited(pid, exitCode2, capsule);
|
|
17148
|
+
})();
|
|
17016
17149
|
});
|
|
17017
17150
|
const immediate = effectiveDetachMs === 0;
|
|
17018
17151
|
const reason = immediate ? `command looks long-running; moved to background immediately (pid=${pid}, label=${label})` : `command detached to background after ${effectiveDetachMs}ms (pid=${pid}, label=${label})`;
|
|
@@ -17036,10 +17169,13 @@ Use listProcesses to inspect or stop it.`,
|
|
|
17036
17169
|
})
|
|
17037
17170
|
};
|
|
17038
17171
|
}
|
|
17039
|
-
const [
|
|
17040
|
-
|
|
17041
|
-
|
|
17172
|
+
const [stdoutCaptureResult, stderrCaptureResult] = await Promise.all([
|
|
17173
|
+
stdoutCapture,
|
|
17174
|
+
stderrCapture
|
|
17042
17175
|
]);
|
|
17176
|
+
const stdout = stdoutCaptureResult.value;
|
|
17177
|
+
const rawStderr = stderrCaptureResult.value;
|
|
17178
|
+
const streamCaptureError = [stdoutCaptureResult.error, stderrCaptureResult.error].filter(Boolean).join("; ");
|
|
17043
17179
|
const exitCode = aborted ? 130 : timedOut ? 124 : Number(raceWinner);
|
|
17044
17180
|
if (typeof proc.pid === "number") {
|
|
17045
17181
|
registry2.completeTransient(proc.pid, exitCode);
|
|
@@ -17456,9 +17592,7 @@ var WORKSPACE_TOOL_NAMES = [
|
|
|
17456
17592
|
"launchProcess",
|
|
17457
17593
|
"listProcesses",
|
|
17458
17594
|
"taskWait",
|
|
17459
|
-
"taskLogs",
|
|
17460
17595
|
"taskStop",
|
|
17461
|
-
"tasks",
|
|
17462
17596
|
"openDesktopPreview"
|
|
17463
17597
|
];
|
|
17464
17598
|
var SHELL_TOOL_NAMES = [
|
|
@@ -17466,9 +17600,7 @@ var SHELL_TOOL_NAMES = [
|
|
|
17466
17600
|
"launchProcess",
|
|
17467
17601
|
"listProcesses",
|
|
17468
17602
|
"taskWait",
|
|
17469
|
-
"
|
|
17470
|
-
"taskStop",
|
|
17471
|
-
"tasks"
|
|
17603
|
+
"taskStop"
|
|
17472
17604
|
];
|
|
17473
17605
|
var WORKSPACE_TOOL_NAME_SET = new Set(WORKSPACE_TOOL_NAMES);
|
|
17474
17606
|
function buildWorkspacePathProperty() {
|
|
@@ -17717,7 +17849,7 @@ function buildTaskWaitTool() {
|
|
|
17717
17849
|
type: "function",
|
|
17718
17850
|
function: {
|
|
17719
17851
|
name: "taskWait",
|
|
17720
|
-
description: 'Block until a background task (from launchProcess, or an execShell command that detached) reaches a terminal state, or until timeoutMs elapses. Returns {outcome, status, exitCode?, cursor, events}: outcome "terminal" with status exited|failed|stopped when it finished, outcome "timeout" with status "running" when it outlived the whole budget, outcome "not-found" for an unknown taskId, or outcome "evicted" when the event trail aged out (never wait again in that case). One call already waits the maximum budget and returns the moment the task ends, so a "timeout" means the task is genuinely longer than that \u2014 go do other work and come back, rather than re-waiting in a loop (each re-wait costs a full model round-trip).
|
|
17852
|
+
description: 'Block until a background task (from launchProcess, or an execShell command that detached) reaches a terminal state, or until timeoutMs elapses. Returns {outcome, status, exitCode?, cursor, events}: outcome "terminal" with status exited|failed|stopped when it finished, outcome "timeout" with status "running" when it outlived the whole budget, outcome "not-found" for an unknown taskId, or outcome "evicted" when the event trail aged out (never wait again in that case). One call already waits the maximum budget and returns the moment the task ends, so a "timeout" means the task is genuinely longer than that \u2014 go do other work and come back, rather than re-waiting in a loop (each re-wait costs a full model round-trip). Pass a small timeoutMs for a cheap liveness peek instead of the full result. `cursor` is the highest event seq covered by this response.',
|
|
17721
17853
|
parameters: {
|
|
17722
17854
|
type: "object",
|
|
17723
17855
|
properties: {
|
|
@@ -17736,30 +17868,6 @@ function buildTaskWaitTool() {
|
|
|
17736
17868
|
}
|
|
17737
17869
|
};
|
|
17738
17870
|
}
|
|
17739
|
-
function buildTaskLogsTool() {
|
|
17740
|
-
return {
|
|
17741
|
-
type: "function",
|
|
17742
|
-
function: {
|
|
17743
|
-
name: "taskLogs",
|
|
17744
|
-
description: "Read a background task's lifecycle events incrementally. Returns {outcome, status, cursor, events} where events are the started|promoted|exited|killed records with seq greater than the cursor you passed, and the returned `cursor` is the new high-water mark to pass next time (omit cursor to read from the beginning; repeating the same cursor is idempotent). Oversized output is spilled to a file and reported as `logRef`, which you can open with readFile.",
|
|
17745
|
-
parameters: {
|
|
17746
|
-
type: "object",
|
|
17747
|
-
properties: {
|
|
17748
|
-
taskId: {
|
|
17749
|
-
type: "string",
|
|
17750
|
-
minLength: 1,
|
|
17751
|
-
description: "Task id returned by launchProcess or by a detached execShell result."
|
|
17752
|
-
},
|
|
17753
|
-
cursor: {
|
|
17754
|
-
type: "number",
|
|
17755
|
-
description: "Last event seq you already consumed; only events with a higher seq are returned. Defaults to 0 (all retained events)."
|
|
17756
|
-
}
|
|
17757
|
-
},
|
|
17758
|
-
required: ["taskId"]
|
|
17759
|
-
}
|
|
17760
|
-
}
|
|
17761
|
-
};
|
|
17762
|
-
}
|
|
17763
17871
|
function buildTaskStopTool() {
|
|
17764
17872
|
return {
|
|
17765
17873
|
type: "function",
|
|
@@ -17780,19 +17888,6 @@ function buildTaskStopTool() {
|
|
|
17780
17888
|
}
|
|
17781
17889
|
};
|
|
17782
17890
|
}
|
|
17783
|
-
function buildTasksTool() {
|
|
17784
|
-
return {
|
|
17785
|
-
type: "function",
|
|
17786
|
-
function: {
|
|
17787
|
-
name: "tasks",
|
|
17788
|
-
description: "List background tasks you can still wait on, read logs from, or stop. Returns {count, tasks: {taskId, pid, label, status, startedAt, persist}[]}. Use it to recover a taskId you lost track of; foreground commands still running inside execShell are not listed.",
|
|
17789
|
-
parameters: {
|
|
17790
|
-
type: "object",
|
|
17791
|
-
properties: {}
|
|
17792
|
-
}
|
|
17793
|
-
}
|
|
17794
|
-
};
|
|
17795
|
-
}
|
|
17796
17891
|
function buildWorkspaceToolDefinition(toolName) {
|
|
17797
17892
|
if (toolName === "readFile") {
|
|
17798
17893
|
return buildReadWorkspaceFileTool();
|
|
@@ -17812,9 +17907,7 @@ function buildWorkspaceToolDefinition(toolName) {
|
|
|
17812
17907
|
if (toolName === "openDesktopPreview") return buildOpenDesktopPreviewTool();
|
|
17813
17908
|
if (toolName === "listProcesses") return buildListProcessesTool();
|
|
17814
17909
|
if (toolName === "taskWait") return buildTaskWaitTool();
|
|
17815
|
-
if (toolName === "taskLogs") return buildTaskLogsTool();
|
|
17816
17910
|
if (toolName === "taskStop") return buildTaskStopTool();
|
|
17817
|
-
if (toolName === "tasks") return buildTasksTool();
|
|
17818
17911
|
return null;
|
|
17819
17912
|
}
|
|
17820
17913
|
function filterDeclaredWorkspaceToolNames(args2) {
|
|
@@ -18923,7 +19016,7 @@ async function launchProcessTool(args2) {
|
|
|
18923
19016
|
};
|
|
18924
19017
|
}
|
|
18925
19018
|
async function listProcessesTool(args2) {
|
|
18926
|
-
const list = getProcessRegistry().list();
|
|
19019
|
+
const list = getProcessRegistry().list().map(toProcessTaskView);
|
|
18927
19020
|
return {
|
|
18928
19021
|
content: JSON.stringify(list),
|
|
18929
19022
|
metadata: {
|
|
@@ -19280,15 +19373,23 @@ function buildLoadSkillExecutor(args2) {
|
|
|
19280
19373
|
const { resolveSkillByName } = await import("./skillDiscovery-CYUCJMAG.js");
|
|
19281
19374
|
const resolved = resolveSkillByName(args2.cwd, name);
|
|
19282
19375
|
if (!resolved) {
|
|
19283
|
-
const {
|
|
19284
|
-
const
|
|
19285
|
-
if (
|
|
19286
|
-
const body = buildCodingSkillContentBySlug(builtinSlug);
|
|
19376
|
+
const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-FUAVTRVZ.js");
|
|
19377
|
+
const builtin = resolveBuiltinSkillByName(name);
|
|
19378
|
+
if (builtin) {
|
|
19287
19379
|
return {
|
|
19288
19380
|
content: `Skill "${name}" loaded inline. Follow its instructions.
|
|
19289
19381
|
|
|
19290
|
-
${
|
|
19291
|
-
|
|
19382
|
+
${builtin.content}`,
|
|
19383
|
+
// toolNames 进 metadata:回退面已扩到全注册表,其中授工具型 skill
|
|
19384
|
+
// (search-* 等)的工具在本宿主未必接线,宿主可据此降级提示。
|
|
19385
|
+
metadata: {
|
|
19386
|
+
loadSkill: true,
|
|
19387
|
+
resolved: true,
|
|
19388
|
+
name,
|
|
19389
|
+
requestedName: name,
|
|
19390
|
+
builtin: true,
|
|
19391
|
+
...builtin.config.toolNames?.length ? { toolNames: [...builtin.config.toolNames] } : {}
|
|
19392
|
+
}
|
|
19292
19393
|
};
|
|
19293
19394
|
}
|
|
19294
19395
|
return {
|
|
@@ -20059,6 +20160,508 @@ async function fetchAntigravityCloudCodeCompletion(args2) {
|
|
|
20059
20160
|
return normalized;
|
|
20060
20161
|
}
|
|
20061
20162
|
|
|
20163
|
+
// packages/agent-runtime/devin/devinProvider.ts
|
|
20164
|
+
import { randomBytes, randomUUID as randomUUID2 } from "node:crypto";
|
|
20165
|
+
var CLIENT_NAME = "chisel";
|
|
20166
|
+
var CLIENT_VERSION = "2026.8.18";
|
|
20167
|
+
function writeVarint(fieldNum, value) {
|
|
20168
|
+
const tag = fieldNum << 3 | 0;
|
|
20169
|
+
const bytes = [];
|
|
20170
|
+
let t = tag;
|
|
20171
|
+
while (t >= 128) {
|
|
20172
|
+
bytes.push(t & 127 | 128);
|
|
20173
|
+
t >>>= 7;
|
|
20174
|
+
}
|
|
20175
|
+
bytes.push(t);
|
|
20176
|
+
let v = value;
|
|
20177
|
+
while (v >= 128) {
|
|
20178
|
+
bytes.push(v & 127 | 128);
|
|
20179
|
+
v >>>= 7;
|
|
20180
|
+
}
|
|
20181
|
+
bytes.push(v);
|
|
20182
|
+
return Buffer.from(bytes);
|
|
20183
|
+
}
|
|
20184
|
+
function writeLengthDelimited(fieldNum, content) {
|
|
20185
|
+
const tag = fieldNum << 3 | 2;
|
|
20186
|
+
const tagBytes = [];
|
|
20187
|
+
let t = tag;
|
|
20188
|
+
while (t >= 128) {
|
|
20189
|
+
tagBytes.push(t & 127 | 128);
|
|
20190
|
+
t >>>= 7;
|
|
20191
|
+
}
|
|
20192
|
+
tagBytes.push(t);
|
|
20193
|
+
const lenBytes = [];
|
|
20194
|
+
let len = content.length;
|
|
20195
|
+
while (len >= 128) {
|
|
20196
|
+
lenBytes.push(len & 127 | 128);
|
|
20197
|
+
len >>>= 7;
|
|
20198
|
+
}
|
|
20199
|
+
lenBytes.push(len);
|
|
20200
|
+
return Buffer.concat([Buffer.from(tagBytes), Buffer.from(lenBytes), content]);
|
|
20201
|
+
}
|
|
20202
|
+
function writeStringField(fieldNum, str) {
|
|
20203
|
+
return writeLengthDelimited(fieldNum, Buffer.from(str, "utf8"));
|
|
20204
|
+
}
|
|
20205
|
+
function writeMessageField(fieldNum, message) {
|
|
20206
|
+
return writeLengthDelimited(fieldNum, message);
|
|
20207
|
+
}
|
|
20208
|
+
function generateFingerprint() {
|
|
20209
|
+
return randomBytes(366).toString("hex");
|
|
20210
|
+
}
|
|
20211
|
+
function encodeDevinClientMetadata(token) {
|
|
20212
|
+
return Buffer.concat([
|
|
20213
|
+
writeStringField(1, CLIENT_NAME),
|
|
20214
|
+
writeStringField(2, CLIENT_VERSION),
|
|
20215
|
+
writeStringField(3, token),
|
|
20216
|
+
writeStringField(4, "en"),
|
|
20217
|
+
writeStringField(5, process.platform === "win32" ? "windows" : "linux"),
|
|
20218
|
+
writeStringField(7, CLIENT_VERSION),
|
|
20219
|
+
writeStringField(12, CLIENT_NAME),
|
|
20220
|
+
writeStringField(31, generateFingerprint())
|
|
20221
|
+
]);
|
|
20222
|
+
}
|
|
20223
|
+
function encodeDevinChatMessage(msg) {
|
|
20224
|
+
const source = msg.role === "assistant" ? 2 : msg.role === "tool" ? 4 : 1;
|
|
20225
|
+
return Buffer.concat([
|
|
20226
|
+
writeStringField(1, randomUUID2()),
|
|
20227
|
+
writeVarint(2, source),
|
|
20228
|
+
writeStringField(3, msg.text),
|
|
20229
|
+
...(msg.toolCalls ?? []).map(
|
|
20230
|
+
(toolCall) => writeMessageField(
|
|
20231
|
+
6,
|
|
20232
|
+
Buffer.concat([
|
|
20233
|
+
writeStringField(1, toolCall.id),
|
|
20234
|
+
writeStringField(2, toolCall.function.name),
|
|
20235
|
+
writeStringField(3, toolCall.function.arguments)
|
|
20236
|
+
])
|
|
20237
|
+
)
|
|
20238
|
+
),
|
|
20239
|
+
...msg.toolCallId ? [writeStringField(7, msg.toolCallId)] : []
|
|
20240
|
+
]);
|
|
20241
|
+
}
|
|
20242
|
+
function encodeDevinToolDefinition(tool) {
|
|
20243
|
+
const fn3 = tool.function ?? {};
|
|
20244
|
+
const name = typeof fn3.name === "string" ? fn3.name : "";
|
|
20245
|
+
const description = typeof fn3.description === "string" ? fn3.description : "";
|
|
20246
|
+
const parameters = fn3.parameters ?? {};
|
|
20247
|
+
return Buffer.concat([
|
|
20248
|
+
writeStringField(1, name),
|
|
20249
|
+
writeStringField(2, description.length > 6998 ? `${description.slice(0, 6995)}...` : description),
|
|
20250
|
+
writeStringField(3, JSON.stringify(parameters))
|
|
20251
|
+
]);
|
|
20252
|
+
}
|
|
20253
|
+
function writeFixed64Field(fieldNum, val) {
|
|
20254
|
+
const b = Buffer.alloc(8);
|
|
20255
|
+
b.writeDoubleLE(val, 0);
|
|
20256
|
+
const tag = fieldNum << 3 | 1;
|
|
20257
|
+
const tagBytes = [];
|
|
20258
|
+
let t = tag;
|
|
20259
|
+
while (t >= 128) {
|
|
20260
|
+
tagBytes.push(t & 127 | 128);
|
|
20261
|
+
t >>>= 7;
|
|
20262
|
+
}
|
|
20263
|
+
tagBytes.push(t);
|
|
20264
|
+
return Buffer.concat([Buffer.from(tagBytes), b]);
|
|
20265
|
+
}
|
|
20266
|
+
function buildCompletionConfig(params) {
|
|
20267
|
+
const maxTokens = params?.maxTokens ?? 128e3;
|
|
20268
|
+
const maxNewlines = params?.maxNewlines ?? 400;
|
|
20269
|
+
const temp = params?.temperature ?? 1;
|
|
20270
|
+
const topP = params?.topP ?? 0.95;
|
|
20271
|
+
return Buffer.concat([
|
|
20272
|
+
writeVarint(1, 1),
|
|
20273
|
+
writeVarint(2, maxTokens),
|
|
20274
|
+
writeVarint(3, maxNewlines),
|
|
20275
|
+
writeFixed64Field(5, temp),
|
|
20276
|
+
writeVarint(7, 40),
|
|
20277
|
+
writeFixed64Field(8, topP)
|
|
20278
|
+
]);
|
|
20279
|
+
}
|
|
20280
|
+
function buildGetChatMessageRequest(params) {
|
|
20281
|
+
const { token, messages, model, tools = [], temperature } = params;
|
|
20282
|
+
const metadata = encodeDevinClientMetadata(token);
|
|
20283
|
+
let systemPrompt = "";
|
|
20284
|
+
const filteredMessages = [];
|
|
20285
|
+
for (const m of messages) {
|
|
20286
|
+
const text = typeof m.content === "string" ? m.content : Array.isArray(m.content) ? m.content.filter((p) => p?.type === "text").map((p) => p.text).join("\n") : "";
|
|
20287
|
+
if (m.role === "system") {
|
|
20288
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
20289
|
+
|
|
20290
|
+
${text}` : text;
|
|
20291
|
+
} else if (m.role === "user" || m.role === "assistant" || m.role === "tool") {
|
|
20292
|
+
filteredMessages.push({
|
|
20293
|
+
role: m.role,
|
|
20294
|
+
text,
|
|
20295
|
+
...m.tool_call_id ? { toolCallId: m.tool_call_id } : {},
|
|
20296
|
+
...m.tool_calls?.length ? { toolCalls: m.tool_calls } : {}
|
|
20297
|
+
});
|
|
20298
|
+
}
|
|
20299
|
+
}
|
|
20300
|
+
const coalesced = [];
|
|
20301
|
+
for (const item of filteredMessages) {
|
|
20302
|
+
const last = coalesced[coalesced.length - 1];
|
|
20303
|
+
if (last && last.role === item.role && item.role !== "tool" && !last.toolCalls?.length && !item.toolCalls?.length) {
|
|
20304
|
+
last.text = `${last.text}
|
|
20305
|
+
|
|
20306
|
+
${item.text}`;
|
|
20307
|
+
} else {
|
|
20308
|
+
coalesced.push({ ...item });
|
|
20309
|
+
}
|
|
20310
|
+
}
|
|
20311
|
+
const chatMessageBuffers = coalesced.map((m) => encodeDevinChatMessage(m));
|
|
20312
|
+
const completionConfig = buildCompletionConfig({ temperature });
|
|
20313
|
+
const modelConfig = Buffer.concat([
|
|
20314
|
+
writeStringField(1, randomUUID2()),
|
|
20315
|
+
writeVarint(2, 1),
|
|
20316
|
+
writeVarint(3, 4)
|
|
20317
|
+
]);
|
|
20318
|
+
return Buffer.concat([
|
|
20319
|
+
writeMessageField(1, metadata),
|
|
20320
|
+
writeStringField(2, systemPrompt),
|
|
20321
|
+
...chatMessageBuffers.map((b) => writeMessageField(3, b)),
|
|
20322
|
+
writeVarint(7, 5),
|
|
20323
|
+
writeMessageField(8, completionConfig),
|
|
20324
|
+
...tools.map((tool) => writeMessageField(10, encodeDevinToolDefinition(tool))),
|
|
20325
|
+
writeMessageField(15, modelConfig),
|
|
20326
|
+
writeStringField(16, randomUUID2()),
|
|
20327
|
+
writeVarint(20, 1),
|
|
20328
|
+
writeStringField(21, model)
|
|
20329
|
+
]);
|
|
20330
|
+
}
|
|
20331
|
+
function buildDevinConnectFrame(payload, flags = 0) {
|
|
20332
|
+
const header = Buffer.alloc(5);
|
|
20333
|
+
header[0] = flags & 255;
|
|
20334
|
+
header.writeUInt32BE(payload.length, 1);
|
|
20335
|
+
return Buffer.concat([header, payload]);
|
|
20336
|
+
}
|
|
20337
|
+
function parseDevinConnectFrames(buffer3) {
|
|
20338
|
+
const frames = [];
|
|
20339
|
+
let offset = 0;
|
|
20340
|
+
while (offset + 5 <= buffer3.length) {
|
|
20341
|
+
const flags = buffer3[offset];
|
|
20342
|
+
const length = buffer3.readUInt32BE(offset + 1);
|
|
20343
|
+
if (offset + 5 + length > buffer3.length) {
|
|
20344
|
+
break;
|
|
20345
|
+
}
|
|
20346
|
+
const payload = buffer3.subarray(offset + 5, offset + 5 + length);
|
|
20347
|
+
frames.push({ flags, payload });
|
|
20348
|
+
offset += 5 + length;
|
|
20349
|
+
}
|
|
20350
|
+
return {
|
|
20351
|
+
frames,
|
|
20352
|
+
remainder: buffer3.subarray(offset)
|
|
20353
|
+
};
|
|
20354
|
+
}
|
|
20355
|
+
function parseDevinMetadataUsage(metaBytes) {
|
|
20356
|
+
let prompt = 0;
|
|
20357
|
+
let completion;
|
|
20358
|
+
let cacheRead = 0;
|
|
20359
|
+
let cacheWrite = 0;
|
|
20360
|
+
let sawAny = false;
|
|
20361
|
+
let offset = 0;
|
|
20362
|
+
while (offset < metaBytes.length) {
|
|
20363
|
+
let tag = 0;
|
|
20364
|
+
let shift = 0;
|
|
20365
|
+
while (offset < metaBytes.length) {
|
|
20366
|
+
const b = metaBytes[offset++];
|
|
20367
|
+
tag |= (b & 127) << shift;
|
|
20368
|
+
if (!(b & 128)) break;
|
|
20369
|
+
shift += 7;
|
|
20370
|
+
}
|
|
20371
|
+
const fieldNum = tag >>> 3;
|
|
20372
|
+
const wireType = tag & 7;
|
|
20373
|
+
if (wireType === 0) {
|
|
20374
|
+
let val = 0;
|
|
20375
|
+
let s = 0;
|
|
20376
|
+
while (offset < metaBytes.length) {
|
|
20377
|
+
const b = metaBytes[offset++];
|
|
20378
|
+
val |= (b & 127) << s;
|
|
20379
|
+
if (!(b & 128)) break;
|
|
20380
|
+
s += 7;
|
|
20381
|
+
}
|
|
20382
|
+
if (fieldNum === 2) {
|
|
20383
|
+
prompt = val;
|
|
20384
|
+
sawAny = true;
|
|
20385
|
+
} else if (fieldNum === 3) {
|
|
20386
|
+
completion = val;
|
|
20387
|
+
sawAny = true;
|
|
20388
|
+
} else if (fieldNum === 4) {
|
|
20389
|
+
cacheWrite = val;
|
|
20390
|
+
sawAny = true;
|
|
20391
|
+
} else if (fieldNum === 5) {
|
|
20392
|
+
cacheRead = val;
|
|
20393
|
+
sawAny = true;
|
|
20394
|
+
}
|
|
20395
|
+
} else if (wireType === 2) {
|
|
20396
|
+
let len = 0;
|
|
20397
|
+
let s = 0;
|
|
20398
|
+
while (offset < metaBytes.length) {
|
|
20399
|
+
const b = metaBytes[offset++];
|
|
20400
|
+
len |= (b & 127) << s;
|
|
20401
|
+
if (!(b & 128)) break;
|
|
20402
|
+
s += 7;
|
|
20403
|
+
}
|
|
20404
|
+
offset += len;
|
|
20405
|
+
} else {
|
|
20406
|
+
break;
|
|
20407
|
+
}
|
|
20408
|
+
}
|
|
20409
|
+
return sawAny ? { prompt, completion, cacheRead, cacheWrite } : null;
|
|
20410
|
+
}
|
|
20411
|
+
function parseDevinConnectTrailer(payload) {
|
|
20412
|
+
const text = payload.toString("utf8").trim();
|
|
20413
|
+
if (!text || text === "{}") return null;
|
|
20414
|
+
try {
|
|
20415
|
+
const parsed = JSON.parse(text);
|
|
20416
|
+
if (!parsed.error) {
|
|
20417
|
+
return new Error(`Devin Connect invalid terminal trailer: ${text}`);
|
|
20418
|
+
}
|
|
20419
|
+
const code = typeof parsed.error.code === "string" ? parsed.error.code : "unknown";
|
|
20420
|
+
const message = typeof parsed.error.message === "string" ? parsed.error.message : "Unknown error";
|
|
20421
|
+
return new Error(`Devin Connect upstream error ${code}: ${message}`);
|
|
20422
|
+
} catch {
|
|
20423
|
+
return new Error(`Devin Connect invalid terminal trailer: ${text}`);
|
|
20424
|
+
}
|
|
20425
|
+
}
|
|
20426
|
+
function decodeDevinResponsePayload(payload) {
|
|
20427
|
+
let offset = 0;
|
|
20428
|
+
let content = "";
|
|
20429
|
+
let reasoning = "";
|
|
20430
|
+
let finishReason = null;
|
|
20431
|
+
let usage = null;
|
|
20432
|
+
const events = [];
|
|
20433
|
+
while (offset < payload.length) {
|
|
20434
|
+
let tag = 0;
|
|
20435
|
+
let shift = 0;
|
|
20436
|
+
while (offset < payload.length) {
|
|
20437
|
+
const b = payload[offset++];
|
|
20438
|
+
tag |= (b & 127) << shift;
|
|
20439
|
+
if (!(b & 128)) break;
|
|
20440
|
+
shift += 7;
|
|
20441
|
+
}
|
|
20442
|
+
const fieldNum = tag >>> 3;
|
|
20443
|
+
const wireType = tag & 7;
|
|
20444
|
+
if (wireType === 0) {
|
|
20445
|
+
let val = 0;
|
|
20446
|
+
let s = 0;
|
|
20447
|
+
while (offset < payload.length) {
|
|
20448
|
+
const b = payload[offset++];
|
|
20449
|
+
val |= (b & 127) << s;
|
|
20450
|
+
if (!(b & 128)) break;
|
|
20451
|
+
s += 7;
|
|
20452
|
+
}
|
|
20453
|
+
if (fieldNum === 5) {
|
|
20454
|
+
finishReason = val === 10 ? "tool_calls" : val === 1 || val === 3 ? "length" : "stop";
|
|
20455
|
+
}
|
|
20456
|
+
} else if (wireType === 2) {
|
|
20457
|
+
let len = 0;
|
|
20458
|
+
let s = 0;
|
|
20459
|
+
while (offset < payload.length) {
|
|
20460
|
+
const b = payload[offset++];
|
|
20461
|
+
len |= (b & 127) << s;
|
|
20462
|
+
if (!(b & 128)) break;
|
|
20463
|
+
s += 7;
|
|
20464
|
+
}
|
|
20465
|
+
const valBytes = payload.subarray(offset, offset + len);
|
|
20466
|
+
offset += len;
|
|
20467
|
+
if (fieldNum === 3) {
|
|
20468
|
+
const text = valBytes.toString("utf8");
|
|
20469
|
+
content += text;
|
|
20470
|
+
events.push({ type: "content", text });
|
|
20471
|
+
} else if (fieldNum === 9) {
|
|
20472
|
+
const text = valBytes.toString("utf8");
|
|
20473
|
+
reasoning += text;
|
|
20474
|
+
events.push({ type: "reasoning", text });
|
|
20475
|
+
} else if (fieldNum === 6) {
|
|
20476
|
+
let nestedOffset = 0;
|
|
20477
|
+
let id;
|
|
20478
|
+
let name;
|
|
20479
|
+
let argsDelta;
|
|
20480
|
+
while (nestedOffset < valBytes.length) {
|
|
20481
|
+
let nestedTag = 0;
|
|
20482
|
+
let nestedShift = 0;
|
|
20483
|
+
while (nestedOffset < valBytes.length) {
|
|
20484
|
+
const b = valBytes[nestedOffset++];
|
|
20485
|
+
nestedTag |= (b & 127) << nestedShift;
|
|
20486
|
+
if (!(b & 128)) break;
|
|
20487
|
+
nestedShift += 7;
|
|
20488
|
+
}
|
|
20489
|
+
const nestedField = nestedTag >>> 3;
|
|
20490
|
+
const nestedWire = nestedTag & 7;
|
|
20491
|
+
if (nestedWire !== 2) break;
|
|
20492
|
+
let nestedLength = 0;
|
|
20493
|
+
let lengthShift = 0;
|
|
20494
|
+
while (nestedOffset < valBytes.length) {
|
|
20495
|
+
const b = valBytes[nestedOffset++];
|
|
20496
|
+
nestedLength |= (b & 127) << lengthShift;
|
|
20497
|
+
if (!(b & 128)) break;
|
|
20498
|
+
lengthShift += 7;
|
|
20499
|
+
}
|
|
20500
|
+
const nestedValue = valBytes.subarray(nestedOffset, nestedOffset + nestedLength);
|
|
20501
|
+
nestedOffset += nestedLength;
|
|
20502
|
+
const text = nestedValue.toString("utf8");
|
|
20503
|
+
if (nestedField === 1) id = text;
|
|
20504
|
+
else if (nestedField === 2) name = text;
|
|
20505
|
+
else if (nestedField === 3) argsDelta = (argsDelta ?? "") + text;
|
|
20506
|
+
}
|
|
20507
|
+
if (id !== void 0 && name !== void 0) {
|
|
20508
|
+
events.push({ type: "tool-call-start", id, name });
|
|
20509
|
+
}
|
|
20510
|
+
if (argsDelta !== void 0) {
|
|
20511
|
+
events.push({ type: "tool-call-args", argsDelta, ...id ? { id } : {} });
|
|
20512
|
+
}
|
|
20513
|
+
} else if (fieldNum === 7) {
|
|
20514
|
+
usage = parseDevinMetadataUsage(valBytes);
|
|
20515
|
+
}
|
|
20516
|
+
} else {
|
|
20517
|
+
break;
|
|
20518
|
+
}
|
|
20519
|
+
}
|
|
20520
|
+
return { content, reasoning, finishReason, events, usage };
|
|
20521
|
+
}
|
|
20522
|
+
function createDevinProvider(options) {
|
|
20523
|
+
const { token, model = "swe-2-max", fetchImpl = fetch, tools = [], temperature } = options;
|
|
20524
|
+
return {
|
|
20525
|
+
model,
|
|
20526
|
+
async complete(messages, opts) {
|
|
20527
|
+
const selectedModel = model;
|
|
20528
|
+
const requestPayload = buildGetChatMessageRequest({
|
|
20529
|
+
token,
|
|
20530
|
+
messages,
|
|
20531
|
+
model: selectedModel,
|
|
20532
|
+
tools,
|
|
20533
|
+
temperature
|
|
20534
|
+
});
|
|
20535
|
+
const frame = buildDevinConnectFrame(requestPayload);
|
|
20536
|
+
const response = await fetchImpl(DEVIN_CONNECT_URL, {
|
|
20537
|
+
method: "POST",
|
|
20538
|
+
headers: {
|
|
20539
|
+
"authorization": `Basic ${token}-${token}`,
|
|
20540
|
+
"content-type": "application/connect+proto",
|
|
20541
|
+
"connect-protocol-version": "1"
|
|
20542
|
+
},
|
|
20543
|
+
body: new Uint8Array(frame),
|
|
20544
|
+
signal: opts?.signal
|
|
20545
|
+
});
|
|
20546
|
+
if (!response.ok) {
|
|
20547
|
+
const errText = await response.text().catch(() => "");
|
|
20548
|
+
throw new Error(
|
|
20549
|
+
`Devin Connect upstream returned error ${response.status}: ${errText}`
|
|
20550
|
+
);
|
|
20551
|
+
}
|
|
20552
|
+
if (!response.body) {
|
|
20553
|
+
throw new Error("Devin Connect response body is null");
|
|
20554
|
+
}
|
|
20555
|
+
let text = "";
|
|
20556
|
+
let reasoning = "";
|
|
20557
|
+
let finishReason = null;
|
|
20558
|
+
let frameUsage = null;
|
|
20559
|
+
const toolCallOrder = [];
|
|
20560
|
+
const toolCallById = /* @__PURE__ */ new Map();
|
|
20561
|
+
let currentToolCallId = null;
|
|
20562
|
+
let buffer3 = Buffer.alloc(0);
|
|
20563
|
+
let sawTrailer = false;
|
|
20564
|
+
const reader = response.body.getReader();
|
|
20565
|
+
try {
|
|
20566
|
+
while (true) {
|
|
20567
|
+
const { done: done4, value } = await reader.read();
|
|
20568
|
+
if (done4) break;
|
|
20569
|
+
buffer3 = Buffer.concat([buffer3, Buffer.from(value)]);
|
|
20570
|
+
const { frames, remainder } = parseDevinConnectFrames(buffer3);
|
|
20571
|
+
buffer3 = Buffer.from(remainder);
|
|
20572
|
+
for (const f of frames) {
|
|
20573
|
+
if (sawTrailer) {
|
|
20574
|
+
throw new Error("Devin Connect received a frame after the terminal trailer");
|
|
20575
|
+
}
|
|
20576
|
+
if (f.flags & 2) {
|
|
20577
|
+
sawTrailer = true;
|
|
20578
|
+
const trailerError = parseDevinConnectTrailer(f.payload);
|
|
20579
|
+
if (trailerError) throw trailerError;
|
|
20580
|
+
continue;
|
|
20581
|
+
}
|
|
20582
|
+
const delta = decodeDevinResponsePayload(f.payload);
|
|
20583
|
+
if (delta.usage?.completion !== void 0) {
|
|
20584
|
+
frameUsage = delta.usage;
|
|
20585
|
+
}
|
|
20586
|
+
text += delta.content;
|
|
20587
|
+
reasoning += delta.reasoning;
|
|
20588
|
+
if (delta.finishReason) finishReason = delta.finishReason;
|
|
20589
|
+
for (const event of delta.events) {
|
|
20590
|
+
if (event.type === "reasoning") {
|
|
20591
|
+
opts?.onReasoningDelta?.(event.text);
|
|
20592
|
+
} else if (event.type === "content") {
|
|
20593
|
+
opts?.onTextDelta?.(event.text);
|
|
20594
|
+
} else if (event.type === "tool-call-start") {
|
|
20595
|
+
const existing = toolCallById.get(event.id);
|
|
20596
|
+
if (existing) {
|
|
20597
|
+
existing.name = event.name;
|
|
20598
|
+
} else {
|
|
20599
|
+
toolCallOrder.push(event.id);
|
|
20600
|
+
toolCallById.set(event.id, {
|
|
20601
|
+
id: event.id,
|
|
20602
|
+
name: event.name,
|
|
20603
|
+
argumentsText: ""
|
|
20604
|
+
});
|
|
20605
|
+
}
|
|
20606
|
+
currentToolCallId = event.id;
|
|
20607
|
+
} else {
|
|
20608
|
+
const targetId = event.id ?? currentToolCallId;
|
|
20609
|
+
const target = targetId ? toolCallById.get(targetId) : void 0;
|
|
20610
|
+
if (target) target.argumentsText += event.argsDelta;
|
|
20611
|
+
}
|
|
20612
|
+
}
|
|
20613
|
+
}
|
|
20614
|
+
}
|
|
20615
|
+
} finally {
|
|
20616
|
+
reader.releaseLock();
|
|
20617
|
+
}
|
|
20618
|
+
if (buffer3.length > 0) {
|
|
20619
|
+
throw new Error("Devin Connect upstream ended with an incomplete frame");
|
|
20620
|
+
}
|
|
20621
|
+
if (!sawTrailer) {
|
|
20622
|
+
throw new Error("Devin Connect upstream ended before the terminal trailer");
|
|
20623
|
+
}
|
|
20624
|
+
const toolCalls = toolCallOrder.map((id) => {
|
|
20625
|
+
const call = toolCallById.get(id);
|
|
20626
|
+
return {
|
|
20627
|
+
id: call.id,
|
|
20628
|
+
type: "function",
|
|
20629
|
+
function: {
|
|
20630
|
+
name: call.name,
|
|
20631
|
+
arguments: call.argumentsText || "{}"
|
|
20632
|
+
}
|
|
20633
|
+
};
|
|
20634
|
+
});
|
|
20635
|
+
if (!text && !reasoning && toolCalls.length === 0) {
|
|
20636
|
+
throw new Error("Devin Connect upstream completed without content or tool calls");
|
|
20637
|
+
}
|
|
20638
|
+
const usage = frameUsage ? {
|
|
20639
|
+
prompt_tokens: frameUsage.prompt + frameUsage.cacheRead,
|
|
20640
|
+
completion_tokens: frameUsage.completion ?? 0,
|
|
20641
|
+
total_tokens: frameUsage.prompt + frameUsage.cacheRead + (frameUsage.completion ?? 0) + frameUsage.cacheWrite,
|
|
20642
|
+
...frameUsage.cacheRead > 0 ? { prompt_tokens_details: { cached_tokens: frameUsage.cacheRead } } : {},
|
|
20643
|
+
...frameUsage.cacheWrite > 0 ? { cache_creation_input_tokens: frameUsage.cacheWrite } : {}
|
|
20644
|
+
} : void 0;
|
|
20645
|
+
return {
|
|
20646
|
+
content: text,
|
|
20647
|
+
model: selectedModel,
|
|
20648
|
+
provider: "devin",
|
|
20649
|
+
...usage ? { usage } : {},
|
|
20650
|
+
...reasoning ? { reasoning_content: reasoning } : {},
|
|
20651
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
|
|
20652
|
+
// The upstream finish event wins whenever it is present. A tool call
|
|
20653
|
+
// cut off by the length limit has to stay "length" instead of being
|
|
20654
|
+
// relabelled "tool_calls", so probes/telemetry and any downstream
|
|
20655
|
+
// consumer of the final finish_reason no longer see a truncated turn
|
|
20656
|
+
// mislabelled as a normal one. localLoop keeps its own truncation
|
|
20657
|
+
// gates and excludes tool-bearing turns from them.
|
|
20658
|
+
finish_reason: finishReason ?? (toolCalls.length > 0 ? "tool_calls" : "stop"),
|
|
20659
|
+
stream_complete: true
|
|
20660
|
+
};
|
|
20661
|
+
}
|
|
20662
|
+
};
|
|
20663
|
+
}
|
|
20664
|
+
|
|
20062
20665
|
export {
|
|
20063
20666
|
Option_exports,
|
|
20064
20667
|
Duration_exports,
|
|
@@ -20068,6 +20671,7 @@ export {
|
|
|
20068
20671
|
readActionGate,
|
|
20069
20672
|
evaluateFileWritePolicy,
|
|
20070
20673
|
summarizeToolArguments,
|
|
20674
|
+
formatToolOverflowMarker,
|
|
20071
20675
|
LOCAL_AGENT_CONFIG_MISSING_CODE,
|
|
20072
20676
|
LOCAL_TURN_ABORTED_CODE,
|
|
20073
20677
|
runLocalAgentTurn,
|
|
@@ -20110,5 +20714,6 @@ export {
|
|
|
20110
20714
|
shouldUseGeminiNativeToolRoute,
|
|
20111
20715
|
buildGeminiGenerateContentRequest,
|
|
20112
20716
|
resolveAntigravityFinishReason,
|
|
20113
|
-
fetchAntigravityCloudCodeCompletion
|
|
20717
|
+
fetchAntigravityCloudCodeCompletion,
|
|
20718
|
+
createDevinProvider
|
|
20114
20719
|
};
|