nolo-cli 0.81.0-alpha.1 → 0.81.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.
Files changed (161) hide show
  1. package/README.md +2 -2
  2. package/{_executeModel-L4LCNFID.js → _executeModel-JIG7MRXQ.js} +48 -48
  3. package/{action-D22U6CTH.js → action-YVYQEAAV.js} +11 -11
  4. package/{addContentAction-XAPUTGL4.js → addContentAction-O7R66HEX.js} +9 -9
  5. package/{addDialogAgentAction-M7VLLBZM.js → addDialogAgentAction-74OA7KYP.js} +8 -8
  6. package/{agentDeleteCommand-D2WHTH7S.js → agentDeleteCommand-THAZ5GQS.js} +31 -29
  7. package/{agentEmailCommands-IHSX56GO.js → agentEmailCommands-A7T7AJA4.js} +67 -63
  8. package/{agentGrantCommands-R3VQEZJR.js → agentGrantCommands-M3XFO6EN.js} +2 -2
  9. package/{agentListCommands-R2DGZMFP.js → agentListCommands-BRZFEJQM.js} +40 -32
  10. package/{agentMachineCommands-UYDID3HQ.js → agentMachineCommands-DM4N5PK3.js} +31 -29
  11. package/{agentProviderCommands-65ZC2WB4.js → agentProviderCommands-GNPTL5XR.js} +87 -0
  12. package/{agentPullCommand-N7L2CT7L.js → agentPullCommand-O5MPVJ5E.js} +3 -3
  13. package/agentRecordCommands-TTAEMNHB.js +128 -0
  14. package/{agentRunCommand-5PJF27JP.js → agentRunCommand-JVSTGVG2.js} +65 -61
  15. package/{agentRunControl-T44MESII.js → agentRunControl-WCTKX5VL.js} +2 -2
  16. package/{agentRuntimeLocal-VD4O2QFQ.js → agentRuntimeLocal-73CVIWBB.js} +27 -25
  17. package/{agentSlice-43ORUHTC.js → agentSlice-6X4JL2E3.js} +10 -10
  18. package/{appDeleteCommands-DXJA7XOZ.js → appDeleteCommands-S7CK4OYL.js} +31 -29
  19. package/{appDeployCommands-JL6XJZJE.js → appDeployCommands-U6TMS5GO.js} +31 -29
  20. package/{appDeployStatusCommands-MS2D2R6R.js → appDeployStatusCommands-DTNQJ3LJ.js} +31 -29
  21. package/{appGetCommands-BV2RDCEV.js → appGetCommands-3SHZEQD5.js} +31 -29
  22. package/{appListCommands-E2AM636N.js → appListCommands-E2ZMIUB6.js} +31 -29
  23. package/{authCommand-EVGFLAHO.js → authCommand-F4EFRRX6.js} +164 -24
  24. package/{authCommands-ILTBI6JV.js → authCommands-RGOGCPP6.js} +4 -5
  25. package/builtinSkillRegistry-FUAVTRVZ.js +33 -0
  26. package/{chatQueueReduxAdapter-F3IRDXDQ.js → chatQueueReduxAdapter-LAQEZQKE.js} +24 -24
  27. package/{chromeCommands-VOIRNJBL.js → chromeCommands-FZYAU75D.js} +1 -1
  28. package/{chromeOpsCommands-M7DPCX2T.js → chromeOpsCommands-62P2Q2YB.js} +31 -1
  29. package/{chunk-C3FZR5EC.js → chunk-2F7RJC6L.js} +1 -1
  30. package/{chunk-HQUORJTM.js → chunk-3BMYXEUW.js} +1 -1
  31. package/{chunk-3QPYFHAH.js → chunk-3DII57IT.js} +1 -1
  32. package/{chunk-KIS76A2P.js → chunk-3IIEFNGY.js} +38 -4
  33. package/{chunk-NTW5GWDM.js → chunk-3VNWWVKB.js} +2 -0
  34. package/{chunk-JQBONKAV.js → chunk-3WD6RUUJ.js} +11 -173
  35. package/{chunk-DWUCB2A3.js → chunk-42V6BK2E.js} +1 -1
  36. package/{chunk-GBPZKFYK.js → chunk-53HEEOTT.js} +4 -4
  37. package/{chunk-GEH7MMBB.js → chunk-54ADB4W7.js} +1 -1
  38. package/{chunk-5XTOKQLW.js → chunk-5UTFL4QJ.js} +6 -2
  39. package/chunk-5ZUL4CUO.js +10 -0
  40. package/{chunk-E6RGHPDR.js → chunk-6D6VBVEW.js} +4 -6
  41. package/{chunk-QNWHWBB7.js → chunk-6FVRQBRR.js} +52 -30
  42. package/{chunk-CMH2SYHX.js → chunk-6OZ36FXI.js} +2 -2
  43. package/{chunk-NRALD3CC.js → chunk-76WEAXJB.js} +49 -10
  44. package/{chunk-DFJFH53D.js → chunk-7OLPQSMQ.js} +6 -6
  45. package/{chunk-BYEJ7K2Z.js → chunk-7S4YWN7P.js} +1 -1
  46. package/{chunk-SREASRV5.js → chunk-ABQYVJBJ.js} +1 -1
  47. package/chunk-ACTMNVHM.js +93 -0
  48. package/{chunk-XWNRAIUL.js → chunk-AFUORTY4.js} +6 -16
  49. package/{chunk-WL2RKIBF.js → chunk-BLJWCTRL.js} +1 -1
  50. package/chunk-BNGW5ASC.js +344 -0
  51. package/{chunk-SZLVDREM.js → chunk-BP4XNZRM.js} +3 -3
  52. package/{chunk-2KDR4CWE.js → chunk-BYMV6QZG.js} +24 -1
  53. package/{chunk-MYU3MJCF.js → chunk-DHDMC6FO.js} +175 -7
  54. package/{chunk-4YCRJUQ2.js → chunk-ESWUWEFS.js} +10 -10
  55. package/{chunk-EXMHJN7C.js → chunk-EYAQT56M.js} +4 -3
  56. package/{chunk-CJCJF5XB.js → chunk-FDTR4QJ6.js} +4 -2
  57. package/{chunk-PYXL2CJL.js → chunk-GPCZ7UXG.js} +1 -1
  58. package/{chunk-K7AG465Q.js → chunk-GQBOR3G6.js} +4 -2
  59. package/{chunk-YFADVSZE.js → chunk-H62HCIUP.js} +6 -6
  60. package/{chunk-PZM3EENV.js → chunk-HJUYAD4A.js} +1 -1
  61. package/{chunk-3JQ2NRYU.js → chunk-HVURBGF3.js} +4 -4
  62. package/{chunk-DAIOZ3ZO.js → chunk-HWIZU4OL.js} +13 -15
  63. package/{chunk-ZVN6I33J.js → chunk-IIVGDG4I.js} +6 -5
  64. package/{chunk-UDQWGU7F.js → chunk-J4MOO56S.js} +1 -1
  65. package/{chunk-DSRXPQWA.js → chunk-JAXOVNM4.js} +43 -43
  66. package/{chunk-QQ7SX52C.js → chunk-JCIHVIVG.js} +15 -15
  67. package/{chunk-KC5FAHVS.js → chunk-JEDZAO7L.js} +1 -1
  68. package/{chunk-6XIE5ZGI.js → chunk-JPGCXHNM.js} +1 -1
  69. package/chunk-JRQFUXY7.js +1625 -0
  70. package/{chunk-J4R5XRX5.js → chunk-K4YGZD3P.js} +419 -72
  71. package/chunk-KQ4ONNQD.js +677 -0
  72. package/{chunk-RXX4GDIH.js → chunk-LS2ZANRJ.js} +1 -1
  73. package/{chunk-ODWEZBU6.js → chunk-LXF6XQDT.js} +1219 -57
  74. package/{chunk-CPSZJBLK.js → chunk-LZIWMYX4.js} +105 -26
  75. package/{chunk-BJIRLHJR.js → chunk-M2EJHDJP.js} +4 -0
  76. package/{chunk-EVBFYPDC.js → chunk-MC4XLIJ7.js} +6 -2
  77. package/{chunk-QC5LGHYP.js → chunk-OF7AQZUG.js} +10 -5
  78. package/{chunk-UJ63UXGE.js → chunk-OIVSQH2O.js} +1006 -801
  79. package/{chunk-AETZ7AD6.js → chunk-Q554LLSI.js} +1 -1
  80. package/chunk-Q5FJJ6XI.js +103 -0
  81. package/{chunk-AJHEFRGJ.js → chunk-Q67DOFOO.js} +214 -5
  82. package/{chunk-UZ6XXCVR.js → chunk-QDSINZM3.js} +15 -2
  83. package/{chunk-D6XYLSOS.js → chunk-QIAVMDHY.js} +1 -1
  84. package/{chunk-IHTVDCWH.js → chunk-R2B3MIZA.js} +3 -3
  85. package/{chunk-YWG6EMH3.js → chunk-RG6JBBX5.js} +10 -6
  86. package/{chunk-QCZX4FTW.js → chunk-SH43IESU.js} +173 -15
  87. package/{chunk-FNGAF7C4.js → chunk-SNPMM7H3.js} +137 -12
  88. package/{chunk-XKNBWXDH.js → chunk-SQQVLHMH.js} +7 -7
  89. package/{chunk-SPAQ4PVV.js → chunk-SV5IJK6K.js} +1 -1
  90. package/{chunk-KVDUCO4Q.js → chunk-TDRTS7QW.js} +16 -12
  91. package/{chunk-BJCWNHVU.js → chunk-TOP2VXOR.js} +2 -2
  92. package/{chunk-QQBO3LQW.js → chunk-TZJJ77KQ.js} +155 -795
  93. package/{chunk-4EJ5QYB5.js → chunk-UKZDAFYT.js} +1 -1
  94. package/{chunk-PGSKWZCB.js → chunk-UZGQNTVW.js} +1 -1
  95. package/{chunk-ZZCJUXUI.js → chunk-V4MJDUSR.js} +2 -2
  96. package/{chunk-JYYZCK2Z.js → chunk-V7E4PXQD.js} +1 -1
  97. package/{chunk-OZX2IPKM.js → chunk-VLTIYV3X.js} +1 -1
  98. package/{chunk-NHRQCXIQ.js → chunk-VMFTFOWF.js} +13 -3
  99. package/{chunk-E36HZARC.js → chunk-WADCY6G6.js} +3 -3
  100. package/{chunk-HH65VA5U.js → chunk-WGR3J4Q6.js} +101 -4
  101. package/{chunk-5J7W2VWW.js → chunk-WV42OMV7.js} +6 -265
  102. package/{chunk-7QHSEMMD.js → chunk-Y5HW6GM2.js} +3 -3
  103. package/{chunk-DUJWWUGV.js → chunk-YQTQQX2H.js} +1 -1
  104. package/{chunk-QPJBFU7R.js → chunk-YVIV7WT4.js} +752 -80
  105. package/{chunk-BOYUESO7.js → chunk-Z77CRGTW.js} +1 -1
  106. package/{chunk-KSHYBTYH.js → chunk-ZWUOR654.js} +932 -299
  107. package/{contentThunks-FSQPOFYG.js → contentThunks-ATLWNC2D.js} +25 -25
  108. package/{cooldownCommands-BSCH2W7P.js → cooldownCommands-REAWYVTY.js} +2 -2
  109. package/{createAgentAutomationAction-VCHDRJ6X.js → createAgentAutomationAction-QYYWTVUR.js} +25 -25
  110. package/{createDialogAction-KZM5IE4P.js → createDialogAction-7I5VGWCR.js} +28 -28
  111. package/{createPageAction-IGMXJOY3.js → createPageAction-WNURYCWU.js} +26 -26
  112. package/{dbSlice-GKGGFNOB.js → dbSlice-XVWBAGYN.js} +8 -8
  113. package/{deleteFile-LWSR674W.js → deleteFile-YG6QMJLU.js} +3 -3
  114. package/{dialogCommands-KJS57EDF.js → dialogCommands-RILHDRQ5.js} +35 -31
  115. package/{dialogSlice-YBTC3GAW.js → dialogSlice-W5BYELVR.js} +24 -24
  116. package/{docCreateCommands-MRGXJTB4.js → docCreateCommands-GSTPU7SG.js} +32 -30
  117. package/{docDeleteCommands-YCI75CBU.js → docDeleteCommands-2FC3LSUT.js} +33 -31
  118. package/{docReadCommands-JN3VHTQY.js → docReadCommands-27POBA34.js} +32 -30
  119. package/{docStore-SDPT23I6.js → docStore-7LAHBFP2.js} +9 -9
  120. package/{docUpdateCommands-7KBOENX7.js → docUpdateCommands-U4II6VCO.js} +32 -30
  121. package/{fetchMessages-DRABNDPZ.js → fetchMessages-EIU7UFFK.js} +3 -4
  122. package/{getPricing-HRMSOF3E.js → getPricing-LUSEABA6.js} +4 -4
  123. package/{handleSendMessageAction-356IDG72.js → handleSendMessageAction-SKMJMVRU.js} +24 -24
  124. package/index.js +102 -85
  125. package/{localDialogRead-PUQKFI73.js → localDialogRead-BTFJ4V2I.js} +2 -2
  126. package/{localRuntimeDb-P37ZTX55.js → localRuntimeDb-SYQGUF4U.js} +1 -1
  127. package/{machineCommands-FYIRYMDE.js → machineCommands-S2RNYKVJ.js} +64 -60
  128. package/{machineWsRunDispatch-J2FEYI4T.js → machineWsRunDispatch-JC44LBLP.js} +62 -58
  129. package/{memberThunks-KATHH3F4.js → memberThunks-QGFLFVCI.js} +9 -9
  130. package/{models-GS72DVJS.js → models-T3SG6MJ5.js} +2 -2
  131. package/{offlineMarxistsAgentCommand-GEH6SNNA.js → offlineMarxistsAgentCommand-HGXZV4XJ.js} +1 -1
  132. package/package.json +1 -1
  133. package/providerPresetApply-FG6NZ57W.js +214 -0
  134. package/providerRegistry-757OWH3O.js +31 -0
  135. package/{read-LC6HVYBN.js → read-COE3ZYR6.js} +5 -4
  136. package/{readDocTool-N3ERJHHF.js → readDocTool-5USN4A6V.js} +1 -1
  137. package/{readlineWorkspace-OWBGR7QO.js → readlineWorkspace-VZSBXUH4.js} +188 -109
  138. package/{removeDialogAgentAction-F5GPTALR.js → removeDialogAgentAction-IX3MN2ZO.js} +11 -11
  139. package/{runAgentClientLoop-DKUUFUKT.js → runAgentClientLoop-ZYENU7GH.js} +47 -47
  140. package/{runtimeDoctorCommands-CROTMULY.js → runtimeDoctorCommands-X6WDBEQX.js} +2 -2
  141. package/{setDialogExtraReferencesAction-AY4ZCF3A.js → setDialogExtraReferencesAction-X4HCPNZL.js} +9 -9
  142. package/{setPrimaryDialogAgentAction-HPMG7V3R.js → setPrimaryDialogAgentAction-4GMIQLOD.js} +11 -11
  143. package/{settingSlice-OEJA4NQO.js → settingSlice-ZQZVUPKK.js} +10 -10
  144. package/{spaceCommands-SSLCOSBH.js → spaceCommands-QB3NNEMN.js} +30 -28
  145. package/{streamAgentChatTurn-FHZZCANP.js → streamAgentChatTurn-43GPPQSN.js} +59 -58
  146. package/{switchDialogAgentAction-HMDZTZ4I.js → switchDialogAgentAction-N52LRPA3.js} +8 -8
  147. package/{tableCommands-SUNTHAYX.js → tableCommands-O6NWHFKV.js} +1 -1
  148. package/{toolApiClient-VGYUB4P5.js → toolApiClient-QVJ6HDNN.js} +2 -2
  149. package/{tools-QZJX3BIC.js → tools-SX6Y4STZ.js} +43 -43
  150. package/tuiSummaryLlmCaller-T2SHYMDZ.js +127 -0
  151. package/{updateCommands-Y363MC3L.js → updateCommands-2M74UL7P.js} +2 -2
  152. package/{updateDialogTitleAction-JJPNGTAP.js → updateDialogTitleAction-VAKA4ZNY.js} +45 -28
  153. package/agentRecordCommands-OFYTWZAA.js +0 -124
  154. package/chunk-3IT2PFHL.js +0 -611
  155. package/chunk-I42VC5KR.js +0 -15
  156. package/chunk-NG4UT4K4.js +0 -79
  157. package/codingSkills-E6KSDNSJ.js +0 -48
  158. package/tuiSummaryLlmCaller-3Z24VUWM.js +0 -116
  159. package/{chunk-3RAG2NAD.js → chunk-UKWGR5SS.js} +3 -3
  160. package/{db-VQSAOWAO.js → db-WK5MDZVN.js} +1 -1
  161. 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-QC5LGHYP.js";
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-KIS76A2P.js";
23
+ } from "./chunk-3IIEFNGY.js";
20
24
  import {
21
25
  downgradeUnparsableToolCalls,
22
26
  hasParsableObjectArguments,
@@ -34,13 +38,15 @@ import {
34
38
  TOOL_GUIDED_SECTION_ORDER,
35
39
  buildIdentityBlock,
36
40
  buildRuntimeGuidanceBlocks,
41
+ detectDispatchIntent,
42
+ detectDispatchIntentFromMessages,
37
43
  estimateContextTokens,
38
44
  hashStablePrefixContent,
39
45
  normalizeChatCompletionsBodyForProvider,
40
46
  requiresBareImageUrl,
41
47
  resolveToolGuidedSections,
42
48
  toBareImageUrlMessages
43
- } from "./chunk-CPSZJBLK.js";
49
+ } from "./chunk-LZIWMYX4.js";
44
50
  import {
45
51
  convertMessagesToResponsesInput,
46
52
  extractReasoningFromResponseOutput,
@@ -64,16 +70,16 @@ import {
64
70
  parseNoloWorkspaceToolArguments,
65
71
  readTextStreamUpToChars,
66
72
  resolveNoloDialogInput
67
- } from "./chunk-ZVN6I33J.js";
73
+ } from "./chunk-IIVGDG4I.js";
68
74
  import {
69
75
  getAntigravityUserAgent,
70
76
  readAntigravityProjectId,
71
77
  resolveAntigravityCloudCodeBaseUrl
72
- } from "./chunk-PGSKWZCB.js";
78
+ } from "./chunk-UZGQNTVW.js";
73
79
  import {
74
80
  buildProviderAuthHeaders,
75
81
  buildProviderExecutionPlan
76
- } from "./chunk-CMH2SYHX.js";
82
+ } from "./chunk-6OZ36FXI.js";
77
83
  import {
78
84
  buildDialogFallbackTitleFromUserInput
79
85
  } from "./chunk-2MBTWINN.js";
@@ -87,7 +93,7 @@ import {
87
93
  resolveEmptyAssistantFallbackMessage,
88
94
  resolveEmptyAssistantOutcome,
89
95
  resolveTruncatedReasoningTailLog
90
- } from "./chunk-DSRXPQWA.js";
96
+ } from "./chunk-JAXOVNM4.js";
91
97
  import {
92
98
  COMPACTION_SUMMARY_SCHEMA_VERSION,
93
99
  COMPACTION_SUMMARY_SYSTEM_PROMPT,
@@ -106,7 +112,7 @@ import {
106
112
  resolveCompressionTriggerRatio,
107
113
  truncateToolOutputForContext,
108
114
  withProviderCallTimingFields
109
- } from "./chunk-E36HZARC.js";
115
+ } from "./chunk-WADCY6G6.js";
110
116
  import {
111
117
  estimateTokenCount
112
118
  } from "./chunk-PSCNXBYA.js";
@@ -130,27 +136,25 @@ import {
130
136
  asRecordOrEmpty
131
137
  } from "./chunk-KX6YBIHG.js";
132
138
  import {
139
+ asTrimmedNonEmptyStringArray,
133
140
  dialogMessageKey,
134
141
  dialogMessageRange
135
- } from "./chunk-NHRQCXIQ.js";
142
+ } from "./chunk-VMFTFOWF.js";
136
143
  import {
137
144
  asOptionalFiniteNumber
138
145
  } from "./chunk-WWC7I6TA.js";
139
- import {
140
- asTrimmedNonEmptyStringArray
141
- } from "./chunk-I42VC5KR.js";
142
146
  import {
143
147
  asTrimmedLowercaseString
144
148
  } from "./chunk-QSJ3HFEF.js";
149
+ import {
150
+ isRecord
151
+ } from "./chunk-KUG52IAP.js";
145
152
  import {
146
153
  asTrimmedString
147
154
  } from "./chunk-3EUW3WEO.js";
148
155
  import {
149
156
  asOptionalPositiveFiniteNumber
150
157
  } from "./chunk-U6VC4MU4.js";
151
- import {
152
- isRecord
153
- } from "./chunk-KUG52IAP.js";
154
158
  import {
155
159
  normalizeServerOrigin
156
160
  } from "./chunk-CF7PE763.js";
@@ -12200,8 +12204,208 @@ function summarizeToolArguments(toolName, rawArgs) {
12200
12204
  );
12201
12205
  }
12202
12206
 
12207
+ // packages/agent-runtime/progressGuard.ts
12208
+ var DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS = 5;
12209
+ var DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS = 8;
12210
+ function sortJsonKeys(obj) {
12211
+ if (obj === null || typeof obj !== "object") return obj;
12212
+ if (Array.isArray(obj)) return obj.map(sortJsonKeys);
12213
+ const sorted = {};
12214
+ for (const key of Object.keys(obj).sort()) {
12215
+ sorted[key] = sortJsonKeys(obj[key]);
12216
+ }
12217
+ return sorted;
12218
+ }
12219
+ function normalizeToolArguments(rawArgs) {
12220
+ if (typeof rawArgs !== "string") {
12221
+ try {
12222
+ return JSON.stringify(sortJsonKeys(rawArgs ?? ""));
12223
+ } catch {
12224
+ return String(rawArgs ?? "");
12225
+ }
12226
+ }
12227
+ const trimmed = rawArgs.trim();
12228
+ if (!trimmed) return "";
12229
+ try {
12230
+ const parsed = JSON.parse(trimmed);
12231
+ return JSON.stringify(sortJsonKeys(parsed));
12232
+ } catch {
12233
+ return trimmed;
12234
+ }
12235
+ }
12236
+ function extractNormalizedContentText(content) {
12237
+ if (typeof content === "string") return content.trim();
12238
+ if (!Array.isArray(content)) return "";
12239
+ return content.map((part) => {
12240
+ if (part?.type === "text") return String(part.text ?? "").trim();
12241
+ if (part?.type === "image_url") return `[img:${part.image_url?.url ?? ""}]`;
12242
+ return "";
12243
+ }).filter(Boolean).join("\n");
12244
+ }
12245
+ function buildToolCallsSignature(toolCalls) {
12246
+ if (!toolCalls || toolCalls.length === 0) return "";
12247
+ return toolCalls.map(
12248
+ (tc) => `${tc.function?.name ?? ""}:${normalizeToolArguments(tc.function?.arguments)}`
12249
+ ).join(";;");
12250
+ }
12251
+ function buildAssistantActionFingerprint(result4) {
12252
+ const content = extractNormalizedContentText(result4.content);
12253
+ const reasoning = typeof result4.reasoning_content === "string" ? result4.reasoning_content.trim() : "";
12254
+ let toolCallsSig = buildToolCallsSignature(result4.tool_calls);
12255
+ let hasToolCalls = Array.isArray(result4.tool_calls) && result4.tool_calls.length > 0;
12256
+ if (!toolCallsSig && Array.isArray(result4.output) && result4.output.length > 0) {
12257
+ const blocksToolCalls = result4.output.filter(
12258
+ (b) => b.type === "toolCall"
12259
+ ).map((b) => b.toolCall);
12260
+ if (blocksToolCalls.length > 0) {
12261
+ toolCallsSig = buildToolCallsSignature(blocksToolCalls);
12262
+ hasToolCalls = true;
12263
+ }
12264
+ }
12265
+ const hasNonEmptyText = content.length > 0 || reasoning.length > 0;
12266
+ const fingerprint = `${content}##${reasoning}##${toolCallsSig}`;
12267
+ return {
12268
+ fingerprint,
12269
+ hasNonEmptyText,
12270
+ hasToolCalls,
12271
+ toolCallsSignature: toolCallsSig
12272
+ };
12273
+ }
12274
+ function buildToolResultsSignature(toolExecutions) {
12275
+ if (toolExecutions.length === 0) return "";
12276
+ return toolExecutions.map((exec) => {
12277
+ const contentStr = typeof exec.content === "string" ? exec.content.trim() : "";
12278
+ const metaStr = exec.metadata ? JSON.stringify(sortJsonKeys(exec.metadata)) : "";
12279
+ return `${exec.toolName}:${contentStr}:${metaStr}`;
12280
+ }).join(";;");
12281
+ }
12282
+ function resolveProgressGuardConfig(options, env = typeof process !== "undefined" ? process.env : {}) {
12283
+ const envDisabled = env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "true" || env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "1";
12284
+ const disabled = options?.disabled ?? envDisabled ?? false;
12285
+ const parsePositiveInt = (val, fallback) => {
12286
+ if (typeof val === "number" && Number.isFinite(val) && val >= 1) {
12287
+ return Math.floor(val);
12288
+ }
12289
+ if (typeof val === "string") {
12290
+ const parsed = parseInt(val, 10);
12291
+ if (Number.isFinite(parsed) && parsed >= 1) {
12292
+ return parsed;
12293
+ }
12294
+ }
12295
+ return fallback;
12296
+ };
12297
+ const maxConsecutiveIdenticalRounds = parsePositiveInt(
12298
+ options?.maxConsecutiveIdenticalRounds ?? env.NOLO_LOOP_MAX_IDENTICAL_ROUNDS,
12299
+ DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS
12300
+ );
12301
+ const maxConsecutiveStagnantToolRounds = parsePositiveInt(
12302
+ options?.maxConsecutiveStagnantToolRounds ?? env.NOLO_LOOP_MAX_STAGNANT_TOOL_ROUNDS,
12303
+ DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS
12304
+ );
12305
+ return {
12306
+ disabled,
12307
+ maxConsecutiveIdenticalRounds,
12308
+ maxConsecutiveStagnantToolRounds
12309
+ };
12310
+ }
12311
+ var LocalLoopProgressGuard = class {
12312
+ config;
12313
+ lastAssistantFingerprint = null;
12314
+ lastAssistantHasNonEmptyText = false;
12315
+ consecutiveIdenticalCount = 0;
12316
+ lastToolCallsSignature = null;
12317
+ lastToolResultsSignature = null;
12318
+ consecutiveStagnantToolCount = 0;
12319
+ constructor(config, env) {
12320
+ this.config = resolveProgressGuardConfig(config, env);
12321
+ }
12322
+ /**
12323
+ * 在 LLM 返回 assistant 响应后调用。
12324
+ * 仅在纯文本/无工具调用且实质文本相同达到阈值时直接熔断;
12325
+ * 若存在工具调用,则不在此处熔断,留待工具执行后结合工具结果综合判定。
12326
+ */
12327
+ observeAssistantResponse(result4) {
12328
+ if (this.config.disabled) return { action: "continue" };
12329
+ const { fingerprint, hasNonEmptyText, hasToolCalls } = buildAssistantActionFingerprint(result4);
12330
+ if (this.lastAssistantFingerprint !== null && this.lastAssistantFingerprint === fingerprint) {
12331
+ this.consecutiveIdenticalCount += 1;
12332
+ if (!hasToolCalls && hasNonEmptyText && this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
12333
+ return {
12334
+ action: "stall",
12335
+ reason: "repetition_loop",
12336
+ detail: `Consecutive identical text-only assistant response for ${this.consecutiveIdenticalCount} rounds.`,
12337
+ consecutiveRounds: this.consecutiveIdenticalCount
12338
+ };
12339
+ }
12340
+ } else {
12341
+ this.lastAssistantFingerprint = fingerprint;
12342
+ this.lastAssistantHasNonEmptyText = hasNonEmptyText;
12343
+ this.consecutiveIdenticalCount = 1;
12344
+ }
12345
+ return { action: "continue" };
12346
+ }
12347
+ /**
12348
+ * 在本轮所有工具执行完毕后调用,检查是否陷入停滞死循环。
12349
+ * 只有当工具返回内容与元数据完全无变化时才计入无进展 streak;
12350
+ * 一旦工具结果发生变化(如合法轮询状态推进),立即重置 identical streak,确保绝不误杀正常长任务。
12351
+ */
12352
+ observeToolExecution(toolCalls, toolResults) {
12353
+ if (this.config.disabled) return { action: "continue" };
12354
+ if (!toolCalls || toolCalls.length === 0) return { action: "continue" };
12355
+ const toolCallsSig = buildToolCallsSignature(toolCalls);
12356
+ const toolResultsSig = buildToolResultsSignature(toolResults);
12357
+ const toolCallsUnchanged = this.lastToolCallsSignature !== null && this.lastToolCallsSignature === toolCallsSig;
12358
+ const toolResultsUnchanged = this.lastToolResultsSignature !== null && this.lastToolResultsSignature === toolResultsSig;
12359
+ if (toolCallsUnchanged && toolResultsUnchanged) {
12360
+ this.consecutiveStagnantToolCount += 1;
12361
+ if (this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
12362
+ return {
12363
+ action: "stall",
12364
+ reason: "repetition_loop",
12365
+ detail: `Consecutive identical assistant response with unchanged tool results for ${this.consecutiveIdenticalCount} rounds.`,
12366
+ consecutiveRounds: this.consecutiveIdenticalCount
12367
+ };
12368
+ }
12369
+ if (this.consecutiveStagnantToolCount >= this.config.maxConsecutiveStagnantToolRounds) {
12370
+ return {
12371
+ action: "stall",
12372
+ reason: "stagnant_tool_calls",
12373
+ detail: `Consecutive stagnant tool calls with unchanged results for ${this.consecutiveStagnantToolCount} rounds.`,
12374
+ consecutiveRounds: this.consecutiveStagnantToolCount
12375
+ };
12376
+ }
12377
+ } else {
12378
+ this.lastToolCallsSignature = toolCallsSig;
12379
+ this.lastToolResultsSignature = toolResultsSig;
12380
+ this.consecutiveStagnantToolCount = 1;
12381
+ if (!toolResultsUnchanged) {
12382
+ this.consecutiveIdenticalCount = 1;
12383
+ }
12384
+ }
12385
+ return { action: "continue" };
12386
+ }
12387
+ };
12388
+ function createLocalLoopProgressGuard(config, env) {
12389
+ return new LocalLoopProgressGuard(config, env);
12390
+ }
12391
+
12392
+ // packages/agent-runtime/toolArgumentsFingerprint.ts
12393
+ var hashFingerprintInput = (value) => {
12394
+ let hash2 = 2166136261;
12395
+ for (let index = 0; index < value.length; index += 1) {
12396
+ hash2 ^= value.charCodeAt(index);
12397
+ hash2 = Math.imul(hash2, 16777619);
12398
+ }
12399
+ return (hash2 >>> 0).toString(16).padStart(8, "0");
12400
+ };
12401
+ function buildToolArgumentsFingerprint(rawArguments) {
12402
+ if (rawArguments === void 0 || rawArguments === null) return void 0;
12403
+ const normalized = normalizeToolArguments(rawArguments);
12404
+ return hashFingerprintInput(normalized);
12405
+ }
12406
+
12203
12407
  // 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.`;
12408
+ 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
12409
 
12206
12410
  // packages/agent-runtime/contextBlockScope.ts
12207
12411
  var isContextBlockScope = (value) => {
@@ -12556,224 +12760,39 @@ async function maybeAutoCompactLocalHistory(args2) {
12556
12760
  }
12557
12761
  }
12558
12762
 
12559
- // packages/agent-runtime/progressGuard.ts
12560
- var DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS = 5;
12561
- var DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS = 8;
12562
- function sortJsonKeys(obj) {
12563
- if (obj === null || typeof obj !== "object") return obj;
12564
- if (Array.isArray(obj)) return obj.map(sortJsonKeys);
12565
- const sorted = {};
12566
- for (const key of Object.keys(obj).sort()) {
12567
- sorted[key] = sortJsonKeys(obj[key]);
12763
+ // packages/agent-runtime/localLoop.ts
12764
+ var LOOP_TIMING_ENABLED = typeof process !== "undefined" && process.env?.NOLO_LOOP_TIMING === "1";
12765
+ var LOOP_TIMING_FILE = typeof process !== "undefined" ? process.env?.NOLO_LOOP_TIMING_FILE : void 0;
12766
+ var loopTimingRows = [];
12767
+ var loopTimingLastMark;
12768
+ function loopTimingMark(phase, round) {
12769
+ if (!LOOP_TIMING_ENABLED) return;
12770
+ const now = performance.now();
12771
+ if (loopTimingLastMark !== void 0) {
12772
+ loopTimingRows.push({ phase, round, durationMs: now - loopTimingLastMark });
12568
12773
  }
12569
- return sorted;
12774
+ loopTimingLastMark = now;
12570
12775
  }
12571
- function normalizeToolArguments(rawArgs) {
12572
- if (typeof rawArgs !== "string") {
12776
+ async function loopTimingFlush() {
12777
+ if (!LOOP_TIMING_ENABLED) return;
12778
+ const lines = loopTimingRows.map((row) => JSON.stringify(row)).join("\n");
12779
+ loopTimingRows = [];
12780
+ loopTimingLastMark = void 0;
12781
+ if (!lines) return;
12782
+ if (LOOP_TIMING_FILE) {
12573
12783
  try {
12574
- return JSON.stringify(sortJsonKeys(rawArgs ?? ""));
12784
+ const { appendFileSync } = await import("node:fs");
12785
+ appendFileSync(LOOP_TIMING_FILE, lines + "\n");
12575
12786
  } catch {
12576
- return String(rawArgs ?? "");
12577
12787
  }
12578
- }
12579
- const trimmed = rawArgs.trim();
12580
- if (!trimmed) return "";
12581
- try {
12582
- const parsed = JSON.parse(trimmed);
12583
- return JSON.stringify(sortJsonKeys(parsed));
12584
- } catch {
12585
- return trimmed;
12788
+ } else {
12789
+ process.stderr.write(lines + "\n");
12586
12790
  }
12587
12791
  }
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");
12771
- }
12772
- }
12773
- var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
12774
- function formatToolExecutionError(args2) {
12775
- const message = toErrorMessage(args2.error);
12776
- return `${args2.toolName} failed: ${message}`;
12792
+ var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
12793
+ function formatToolExecutionError(args2) {
12794
+ const message = toErrorMessage(args2.error);
12795
+ return `${args2.toolName} failed: ${message}`;
12777
12796
  }
12778
12797
  function formatStructuredToolExecutionError(args2) {
12779
12798
  if (!args2.error || typeof args2.error !== "object") return null;
@@ -13046,10 +13065,10 @@ var TOOL_METADATA_KEYS = [
13046
13065
  "pasteId",
13047
13066
  "source"
13048
13067
  ];
13049
- function trimHistoryToContextBudget(history, model) {
13068
+ function trimHistoryToContextBudget(history, model, contextWindowOverride) {
13050
13069
  if (history.length === 0) return { history, droppedCount: 0 };
13051
13070
  const { rawMessageBudget } = planContextUsage({
13052
- contextWindow: getModelContextWindow(model ?? ""),
13071
+ contextWindow: contextWindowOverride ?? getModelContextWindow(model ?? ""),
13053
13072
  summaryTokens: 0,
13054
13073
  // localLoop 没有 web 端的负载分档器;medium 是中性默认值,
13055
13074
  // 不为了省几个 token 在这里复制一份分类逻辑。
@@ -13512,7 +13531,14 @@ async function runLocalAgentTurn(input) {
13512
13531
  agentConfig.exposedToolNames ?? agentConfig.toolNames ?? []
13513
13532
  );
13514
13533
  const guidanceBlocks = buildRuntimeGuidanceBlocks(agentTools);
13515
- const toolGuidedSections = resolveToolGuidedSections(agentTools);
13534
+ const toolGuidedSections = resolveToolGuidedSections(agentTools, {
13535
+ // 单调锁定:历史里任一 user 消息命中派发关键词、或已出现过
13536
+ // startAgentRun/controlAgentRun 的 tool_calls,后续每轮都保持 true,
13537
+ // 防止 session-scope 的 agentCollaboration 段逐轮翻转击穿前缀缓存。
13538
+ dispatchIntent: detectDispatchIntentFromMessages(history) || detectDispatchIntent(
13539
+ typeof input.input === "string" ? input.input : void 0
13540
+ )
13541
+ });
13516
13542
  const guidanceScopes = [
13517
13543
  ...input.userLanguage?.trim() ? [buildUserResponseLanguageContext({ language: input.userLanguage })] : [],
13518
13544
  guidanceBlocks.startupProtocol,
@@ -13540,7 +13566,7 @@ async function runLocalAgentTurn(input) {
13540
13566
  }
13541
13567
  return resolvedProvider;
13542
13568
  };
13543
- const contextWindow = getModelContextWindow(agentConfig.model ?? "");
13569
+ const contextWindow = resolveAgentContextWindow(agentConfig);
13544
13570
  const compressionTriggerRatio = resolveCompressionTriggerRatio(contextWindow);
13545
13571
  let realContextUsagePercent;
13546
13572
  if (input.continueDialogId && typeof input.adapter.loadLastContextUsage === "function") {
@@ -13582,6 +13608,7 @@ async function runLocalAgentTurn(input) {
13582
13608
  history,
13583
13609
  model: agentConfig.model,
13584
13610
  resolveProvider: resolveProviderOnce,
13611
+ contextWindow,
13585
13612
  realContextUsagePercent
13586
13613
  });
13587
13614
  history = compacted.history;
@@ -13591,7 +13618,7 @@ async function runLocalAgentTurn(input) {
13591
13618
  console.warn("[localLoop] auto-compaction unexpected error:", error);
13592
13619
  }
13593
13620
  loopTimingMark("maybeAutoCompactLocalHistory", 0);
13594
- const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model);
13621
+ const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model, contextWindow);
13595
13622
  if (trimmedHistory.droppedCount > 0) {
13596
13623
  history = trimmedHistory.history;
13597
13624
  }
@@ -13678,6 +13705,7 @@ async function runLocalAgentTurn(input) {
13678
13705
  ],
13679
13706
  model: agentConfig.model,
13680
13707
  resolveProvider: resolveProviderOnce,
13708
+ contextWindow,
13681
13709
  realContextUsagePercent: ratio
13682
13710
  });
13683
13711
  if (compacted.usage) {
@@ -13946,6 +13974,7 @@ ${reasoningTailLog}
13946
13974
  const startedAt = Date.now();
13947
13975
  loopTimingMark("toolCallStart", round);
13948
13976
  const argumentsPreview = summarizeToolArguments(toolName, toolCall.function.arguments);
13977
+ const argumentsFingerprint = buildToolArgumentsFingerprint(toolCall.function.arguments);
13949
13978
  emitLoopEvent(
13950
13979
  observationBoundary,
13951
13980
  {
@@ -13954,7 +13983,8 @@ ${reasoningTailLog}
13954
13983
  toolCallId: toolCall.id,
13955
13984
  toolName,
13956
13985
  atMs: startedAt,
13957
- ...argumentsPreview ? { argumentsPreview } : {}
13986
+ ...argumentsPreview ? { argumentsPreview } : {},
13987
+ ...argumentsFingerprint ? { argumentsFingerprint } : {}
13958
13988
  },
13959
13989
  {
13960
13990
  type: "tool-call",
@@ -15568,13 +15598,13 @@ var DEFAULT_LOCAL_TOOLS = /* @__PURE__ */ new Set([
15568
15598
  "execShell",
15569
15599
  "launchProcess",
15570
15600
  "listProcesses",
15571
- // ProcessTask follow-up tools (Phase 1). Same tier as listProcesses: they
15572
- // observe/stop tasks the agent itself already spawned, so their blast radius
15573
- // is strictly narrower than launchProcess (which is default-enabled).
15601
+ // ProcessTask follow-up tools. Same tier as listProcesses: they observe/stop
15602
+ // tasks the agent itself already spawned, so their blast radius is strictly
15603
+ // narrower than launchProcess (which is default-enabled). Model-facing
15604
+ // follow-ups are taskWait/taskStop only — lifecycle history (taskLogs) stays
15605
+ // runtime-internal.
15574
15606
  "taskWait",
15575
- "taskLogs",
15576
15607
  "taskStop",
15577
- "tasks",
15578
15608
  // Scheduling tools: forking/observing sub-agents is a declared capability
15579
15609
  // of capable agents, and the blast radius is strictly narrower than
15580
15610
  // execShell (already default-enabled). Requiring an env allowlist for these
@@ -16210,6 +16240,24 @@ var ProcessTaskEventLog = class {
16210
16240
  };
16211
16241
 
16212
16242
  // packages/agent-runtime/processRegistry.ts
16243
+ function toProcessTaskView(record) {
16244
+ const capsule = record.resultCapsule;
16245
+ return {
16246
+ taskId: record.taskId,
16247
+ pid: record.pid,
16248
+ pgid: record.pgid,
16249
+ command: record.command,
16250
+ label: record.label,
16251
+ startedAt: record.startedAt,
16252
+ status: record.status,
16253
+ ...record.exitCode !== void 0 ? { exitCode: record.exitCode } : {},
16254
+ persist: record.persist,
16255
+ promoted: record.promoted,
16256
+ transient: record.transient,
16257
+ ...capsule?.durationMs !== void 0 ? { durationMs: capsule.durationMs } : {},
16258
+ ...capsule?.spill ? { outputRef: capsule.spill.displayPath } : {}
16259
+ };
16260
+ }
16213
16261
  var taskIdCounter = 0;
16214
16262
  function mintTaskId(pid) {
16215
16263
  taskIdCounter += 1;
@@ -16398,10 +16446,11 @@ var ProcessRegistry = class {
16398
16446
  }
16399
16447
  }
16400
16448
  }
16401
- markExited(pid, exitCode) {
16449
+ markExited(pid, exitCode, resultCapsule) {
16402
16450
  const item = this.processes.get(pid);
16403
16451
  if (item && item.status === "running") {
16404
16452
  item.exitCode = exitCode;
16453
+ if (resultCapsule) item.resultCapsule = resultCapsule;
16405
16454
  item.status = exitCode === 0 ? "exited" : "failed";
16406
16455
  this.eventLog.append({
16407
16456
  taskId: item.taskId,
@@ -16416,7 +16465,8 @@ var ProcessRegistry = class {
16416
16465
  command: item.command,
16417
16466
  status: item.status,
16418
16467
  exitCode,
16419
- promoted: item.promoted
16468
+ promoted: item.promoted,
16469
+ ...item.resultCapsule ? { resultCapsule: item.resultCapsule } : {}
16420
16470
  });
16421
16471
  }
16422
16472
  }
@@ -16479,6 +16529,62 @@ function readProcessOwner(runtimeContext) {
16479
16529
  // packages/agent-runtime/workspaceShell.ts
16480
16530
  import { resolve as resolve3 } from "node:path";
16481
16531
  import { spawn as spawnChildProcess2 } from "node:child_process";
16532
+
16533
+ // packages/agent-runtime/processTaskResult.ts
16534
+ var PROCESS_RESULT_CAPSULE_TAIL_CHARS = 4e3;
16535
+ var PROCESS_RESULT_CAPSULE_SPILL_THRESHOLD_CHARS = 2e4;
16536
+ function tailText(value, maxChars) {
16537
+ if (value.length <= maxChars) return { text: value, truncated: false };
16538
+ return { text: value.slice(-maxChars), truncated: true };
16539
+ }
16540
+ function formatCapsuleStream(name, value) {
16541
+ return value.trim() ? `${name}:
16542
+ ${value.replace(/\n+$/, "")}` : "";
16543
+ }
16544
+ function buildProcessTaskResultCapsule(args2) {
16545
+ const tailChars = args2.tailChars ?? PROCESS_RESULT_CAPSULE_TAIL_CHARS;
16546
+ const spillThresholdChars = args2.spillThresholdChars ?? PROCESS_RESULT_CAPSULE_SPILL_THRESHOLD_CHARS;
16547
+ const stdout = typeof args2.stdout === "string" ? args2.stdout : "";
16548
+ const stderr = typeof args2.stderr === "string" ? args2.stderr : "";
16549
+ const exitCode = args2.exitCode;
16550
+ const captureError = args2.captureError?.trim() || void 0;
16551
+ const durationMs = typeof args2.startedAt === "number" && Number.isFinite(args2.startedAt) ? Math.max(0, (args2.endedAt ?? Date.now()) - args2.startedAt) : void 0;
16552
+ const stdoutTail = tailText(stdout, tailChars);
16553
+ const stderrTail = tailText(stderr, tailChars);
16554
+ const inlineSize = stdout.length + stderr.length;
16555
+ const inlineTruncated = stdoutTail.truncated || stderrTail.truncated;
16556
+ const shouldSpill = inlineTruncated || inlineSize > spillThresholdChars;
16557
+ let spill;
16558
+ if (shouldSpill) {
16559
+ try {
16560
+ const result4 = spillToolOutput({
16561
+ content: [
16562
+ formatCapsuleStream("stdout", stdout),
16563
+ formatCapsuleStream("stderr", stderr)
16564
+ ].filter(Boolean).join("\n\n"),
16565
+ toolName: "execShell",
16566
+ ...args2.workspaceRoot !== void 0 ? { workspaceRoot: args2.workspaceRoot } : {}
16567
+ });
16568
+ spill = {
16569
+ displayPath: result4.displayPath,
16570
+ totalChars: result4.totalChars,
16571
+ totalLines: result4.totalLines
16572
+ };
16573
+ } catch {
16574
+ }
16575
+ }
16576
+ return {
16577
+ stdout: stdoutTail.text,
16578
+ stderr: stderrTail.text,
16579
+ exitCode,
16580
+ ...durationMs !== void 0 ? { durationMs } : {},
16581
+ ...captureError ? { captureError } : {},
16582
+ truncated: inlineTruncated || Boolean(captureError),
16583
+ ...spill ? { spill } : {}
16584
+ };
16585
+ }
16586
+
16587
+ // packages/agent-runtime/workspaceShell.ts
16482
16588
  var EXEC_SHELL_TIMEOUT_ENV = "NOLO_EXEC_SHELL_TIMEOUT_MS";
16483
16589
  var EXEC_SHELL_DETACH_ENV = "NOLO_EXEC_SHELL_DETACH_MS";
16484
16590
  var DEFAULT_EXEC_SHELL_DETACH_MS = 12e4;
@@ -16858,6 +16964,15 @@ ${stderr.trim()}`, "exitCode: 127"].filter(Boolean).join("\n\n"),
16858
16964
  )
16859
16965
  };
16860
16966
  }
16967
+ function stdoutPromiseResult(promise3) {
16968
+ return promise3.then(
16969
+ (value) => ({ value }),
16970
+ (error) => ({
16971
+ value: "",
16972
+ error: error instanceof Error ? error.message : String(error)
16973
+ })
16974
+ );
16975
+ }
16861
16976
  async function runWorkspaceCommand(args2) {
16862
16977
  const timeoutMs = asOptionalPositiveFiniteNumber(args2.timeoutMs);
16863
16978
  const detached = process.platform !== "win32";
@@ -16916,8 +17031,8 @@ async function runWorkspaceCommand(args2) {
16916
17031
  process.removeListener("SIGINT", cleanupChildOnHostSignal);
16917
17032
  };
16918
17033
  exitPromise.then(detachSignalCleanup, detachSignalCleanup);
16919
- const stdoutPromise = readNodeStream(proc.stdout);
16920
- const stderrPromise = readNodeStream(proc.stderr);
17034
+ const stdoutCapture = stdoutPromiseResult(readNodeStream(proc.stdout));
17035
+ const stderrCapture = stdoutPromiseResult(readNodeStream(proc.stderr));
16921
17036
  const killChild = (signal) => {
16922
17037
  if (detached && typeof proc.pid === "number") {
16923
17038
  try {
@@ -17016,7 +17131,30 @@ async function runWorkspaceCommand(args2) {
17016
17131
  const taskId = envelope.taskId;
17017
17132
  proc.on("close", (code) => {
17018
17133
  detachSignalCleanup();
17019
- registry2.markExited(pid, code ?? 1);
17134
+ const exitCode2 = code ?? 1;
17135
+ void (async () => {
17136
+ const [stdoutResult, stderrResult] = await Promise.all([
17137
+ stdoutCapture,
17138
+ stderrCapture
17139
+ ]);
17140
+ const stdout2 = stdoutResult.value;
17141
+ const stderr2 = stderrResult.value;
17142
+ let capsule;
17143
+ try {
17144
+ capsule = buildProcessTaskResultCapsule({
17145
+ stdout: stdout2,
17146
+ stderr: stderr2,
17147
+ exitCode: exitCode2,
17148
+ // Duration is measured from the registry envelope's startedAt
17149
+ // (spawn moment), not from the detach moment.
17150
+ startedAt: registry2.get(pid)?.startedAt,
17151
+ workspaceRoot: args2.workspaceRoot,
17152
+ captureError: [stdoutResult.error, stderrResult.error].filter(Boolean).join("; ")
17153
+ });
17154
+ } catch {
17155
+ }
17156
+ registry2.markExited(pid, exitCode2, capsule);
17157
+ })();
17020
17158
  });
17021
17159
  const immediate = effectiveDetachMs === 0;
17022
17160
  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})`;
@@ -17040,10 +17178,13 @@ Use listProcesses to inspect or stop it.`,
17040
17178
  })
17041
17179
  };
17042
17180
  }
17043
- const [stdout, rawStderr] = await Promise.all([
17044
- stdoutPromise,
17045
- stderrPromise
17181
+ const [stdoutCaptureResult, stderrCaptureResult] = await Promise.all([
17182
+ stdoutCapture,
17183
+ stderrCapture
17046
17184
  ]);
17185
+ const stdout = stdoutCaptureResult.value;
17186
+ const rawStderr = stderrCaptureResult.value;
17187
+ const streamCaptureError = [stdoutCaptureResult.error, stderrCaptureResult.error].filter(Boolean).join("; ");
17047
17188
  const exitCode = aborted ? 130 : timedOut ? 124 : Number(raceWinner);
17048
17189
  if (typeof proc.pid === "number") {
17049
17190
  registry2.completeTransient(proc.pid, exitCode);
@@ -17460,9 +17601,7 @@ var WORKSPACE_TOOL_NAMES = [
17460
17601
  "launchProcess",
17461
17602
  "listProcesses",
17462
17603
  "taskWait",
17463
- "taskLogs",
17464
17604
  "taskStop",
17465
- "tasks",
17466
17605
  "openDesktopPreview"
17467
17606
  ];
17468
17607
  var SHELL_TOOL_NAMES = [
@@ -17470,9 +17609,7 @@ var SHELL_TOOL_NAMES = [
17470
17609
  "launchProcess",
17471
17610
  "listProcesses",
17472
17611
  "taskWait",
17473
- "taskLogs",
17474
- "taskStop",
17475
- "tasks"
17612
+ "taskStop"
17476
17613
  ];
17477
17614
  var WORKSPACE_TOOL_NAME_SET = new Set(WORKSPACE_TOOL_NAMES);
17478
17615
  function buildWorkspacePathProperty() {
@@ -17721,7 +17858,7 @@ function buildTaskWaitTool() {
17721
17858
  type: "function",
17722
17859
  function: {
17723
17860
  name: "taskWait",
17724
- 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). For a cheap liveness peek use taskLogs (non-blocking) or pass a small timeoutMs. `cursor` is the highest event seq covered by this response \u2014 pass it to taskLogs to read only newer events.',
17861
+ 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.',
17725
17862
  parameters: {
17726
17863
  type: "object",
17727
17864
  properties: {
@@ -17740,30 +17877,6 @@ function buildTaskWaitTool() {
17740
17877
  }
17741
17878
  };
17742
17879
  }
17743
- function buildTaskLogsTool() {
17744
- return {
17745
- type: "function",
17746
- function: {
17747
- name: "taskLogs",
17748
- 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.",
17749
- parameters: {
17750
- type: "object",
17751
- properties: {
17752
- taskId: {
17753
- type: "string",
17754
- minLength: 1,
17755
- description: "Task id returned by launchProcess or by a detached execShell result."
17756
- },
17757
- cursor: {
17758
- type: "number",
17759
- description: "Last event seq you already consumed; only events with a higher seq are returned. Defaults to 0 (all retained events)."
17760
- }
17761
- },
17762
- required: ["taskId"]
17763
- }
17764
- }
17765
- };
17766
- }
17767
17880
  function buildTaskStopTool() {
17768
17881
  return {
17769
17882
  type: "function",
@@ -17784,19 +17897,6 @@ function buildTaskStopTool() {
17784
17897
  }
17785
17898
  };
17786
17899
  }
17787
- function buildTasksTool() {
17788
- return {
17789
- type: "function",
17790
- function: {
17791
- name: "tasks",
17792
- 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.",
17793
- parameters: {
17794
- type: "object",
17795
- properties: {}
17796
- }
17797
- }
17798
- };
17799
- }
17800
17900
  function buildWorkspaceToolDefinition(toolName) {
17801
17901
  if (toolName === "readFile") {
17802
17902
  return buildReadWorkspaceFileTool();
@@ -17816,9 +17916,7 @@ function buildWorkspaceToolDefinition(toolName) {
17816
17916
  if (toolName === "openDesktopPreview") return buildOpenDesktopPreviewTool();
17817
17917
  if (toolName === "listProcesses") return buildListProcessesTool();
17818
17918
  if (toolName === "taskWait") return buildTaskWaitTool();
17819
- if (toolName === "taskLogs") return buildTaskLogsTool();
17820
17919
  if (toolName === "taskStop") return buildTaskStopTool();
17821
- if (toolName === "tasks") return buildTasksTool();
17822
17920
  return null;
17823
17921
  }
17824
17922
  function filterDeclaredWorkspaceToolNames(args2) {
@@ -18927,7 +19025,7 @@ async function launchProcessTool(args2) {
18927
19025
  };
18928
19026
  }
18929
19027
  async function listProcessesTool(args2) {
18930
- const list = getProcessRegistry().list();
19028
+ const list = getProcessRegistry().list().map(toProcessTaskView);
18931
19029
  return {
18932
19030
  content: JSON.stringify(list),
18933
19031
  metadata: {
@@ -19284,15 +19382,23 @@ function buildLoadSkillExecutor(args2) {
19284
19382
  const { resolveSkillByName } = await import("./skillDiscovery-CYUCJMAG.js");
19285
19383
  const resolved = resolveSkillByName(args2.cwd, name);
19286
19384
  if (!resolved) {
19287
- const { resolveCodingBuiltinSlug, buildCodingSkillContentBySlug } = await import("./codingSkills-E6KSDNSJ.js");
19288
- const builtinSlug = resolveCodingBuiltinSlug(name);
19289
- if (builtinSlug) {
19290
- const body = buildCodingSkillContentBySlug(builtinSlug);
19385
+ const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-FUAVTRVZ.js");
19386
+ const builtin = resolveBuiltinSkillByName(name);
19387
+ if (builtin) {
19291
19388
  return {
19292
19389
  content: `Skill "${name}" loaded inline. Follow its instructions.
19293
19390
 
19294
- ${body}`,
19295
- metadata: { loadSkill: true, resolved: true, name, requestedName: name, builtin: true }
19391
+ ${builtin.content}`,
19392
+ // toolNames 进 metadata:回退面已扩到全注册表,其中授工具型 skill
19393
+ // (search-* 等)的工具在本宿主未必接线,宿主可据此降级提示。
19394
+ metadata: {
19395
+ loadSkill: true,
19396
+ resolved: true,
19397
+ name,
19398
+ requestedName: name,
19399
+ builtin: true,
19400
+ ...builtin.config.toolNames?.length ? { toolNames: [...builtin.config.toolNames] } : {}
19401
+ }
19296
19402
  };
19297
19403
  }
19298
19404
  return {
@@ -20063,6 +20169,530 @@ async function fetchAntigravityCloudCodeCompletion(args2) {
20063
20169
  return normalized;
20064
20170
  }
20065
20171
 
20172
+ // packages/agent-runtime/devin/devinProvider.ts
20173
+ import { randomBytes, randomUUID as randomUUID2 } from "node:crypto";
20174
+ var CLIENT_NAME = "chisel";
20175
+ var CLIENT_VERSION = "2026.8.18";
20176
+ function writeVarint(fieldNum, value) {
20177
+ const tag = fieldNum << 3 | 0;
20178
+ const bytes = [];
20179
+ let t = tag;
20180
+ while (t >= 128) {
20181
+ bytes.push(t & 127 | 128);
20182
+ t >>>= 7;
20183
+ }
20184
+ bytes.push(t);
20185
+ let v = value;
20186
+ while (v >= 128) {
20187
+ bytes.push(v & 127 | 128);
20188
+ v >>>= 7;
20189
+ }
20190
+ bytes.push(v);
20191
+ return Buffer.from(bytes);
20192
+ }
20193
+ function writeLengthDelimited(fieldNum, content) {
20194
+ const tag = fieldNum << 3 | 2;
20195
+ const tagBytes = [];
20196
+ let t = tag;
20197
+ while (t >= 128) {
20198
+ tagBytes.push(t & 127 | 128);
20199
+ t >>>= 7;
20200
+ }
20201
+ tagBytes.push(t);
20202
+ const lenBytes = [];
20203
+ let len = content.length;
20204
+ while (len >= 128) {
20205
+ lenBytes.push(len & 127 | 128);
20206
+ len >>>= 7;
20207
+ }
20208
+ lenBytes.push(len);
20209
+ return Buffer.concat([Buffer.from(tagBytes), Buffer.from(lenBytes), content]);
20210
+ }
20211
+ function writeStringField(fieldNum, str) {
20212
+ return writeLengthDelimited(fieldNum, Buffer.from(str, "utf8"));
20213
+ }
20214
+ function writeMessageField(fieldNum, message) {
20215
+ return writeLengthDelimited(fieldNum, message);
20216
+ }
20217
+ function generateFingerprint() {
20218
+ return randomBytes(366).toString("hex");
20219
+ }
20220
+ function encodeDevinClientMetadata(token) {
20221
+ return Buffer.concat([
20222
+ writeStringField(1, CLIENT_NAME),
20223
+ writeStringField(2, CLIENT_VERSION),
20224
+ writeStringField(3, token),
20225
+ writeStringField(4, "en"),
20226
+ writeStringField(5, process.platform === "win32" ? "windows" : "linux"),
20227
+ writeStringField(7, CLIENT_VERSION),
20228
+ writeStringField(12, CLIENT_NAME),
20229
+ writeStringField(31, generateFingerprint())
20230
+ ]);
20231
+ }
20232
+ function encodeDevinChatMessage(msg) {
20233
+ const source = msg.role === "assistant" ? 2 : msg.role === "tool" ? 4 : 1;
20234
+ return Buffer.concat([
20235
+ writeStringField(1, randomUUID2()),
20236
+ writeVarint(2, source),
20237
+ writeStringField(3, msg.text),
20238
+ ...(msg.toolCalls ?? []).map(
20239
+ (toolCall) => writeMessageField(
20240
+ 6,
20241
+ Buffer.concat([
20242
+ writeStringField(1, toolCall.id),
20243
+ writeStringField(2, toolCall.function.name),
20244
+ writeStringField(3, toolCall.function.arguments)
20245
+ ])
20246
+ )
20247
+ ),
20248
+ ...msg.toolCallId ? [writeStringField(7, msg.toolCallId)] : []
20249
+ ]);
20250
+ }
20251
+ function encodeDevinToolDefinition(tool) {
20252
+ const fn3 = tool.function ?? {};
20253
+ const name = typeof fn3.name === "string" ? fn3.name : "";
20254
+ const description = typeof fn3.description === "string" ? fn3.description : "";
20255
+ const parameters = fn3.parameters ?? {};
20256
+ return Buffer.concat([
20257
+ writeStringField(1, name),
20258
+ writeStringField(2, description.length > 6998 ? `${description.slice(0, 6995)}...` : description),
20259
+ writeStringField(3, JSON.stringify(parameters))
20260
+ ]);
20261
+ }
20262
+ function writeFixed64Field(fieldNum, val) {
20263
+ const b = Buffer.alloc(8);
20264
+ b.writeDoubleLE(val, 0);
20265
+ const tag = fieldNum << 3 | 1;
20266
+ const tagBytes = [];
20267
+ let t = tag;
20268
+ while (t >= 128) {
20269
+ tagBytes.push(t & 127 | 128);
20270
+ t >>>= 7;
20271
+ }
20272
+ tagBytes.push(t);
20273
+ return Buffer.concat([Buffer.from(tagBytes), b]);
20274
+ }
20275
+ function buildCompletionConfig(params) {
20276
+ const maxTokens = params?.maxTokens ?? 128e3;
20277
+ const maxNewlines = params?.maxNewlines ?? 400;
20278
+ const temp = params?.temperature ?? 1;
20279
+ const topP = params?.topP ?? 0.95;
20280
+ return Buffer.concat([
20281
+ writeVarint(1, 1),
20282
+ writeVarint(2, maxTokens),
20283
+ writeVarint(3, maxNewlines),
20284
+ writeFixed64Field(5, temp),
20285
+ writeVarint(7, 40),
20286
+ writeFixed64Field(8, topP)
20287
+ ]);
20288
+ }
20289
+ function buildGetChatMessageRequest(params) {
20290
+ const { token, messages, model, tools = [], temperature } = params;
20291
+ const metadata = encodeDevinClientMetadata(token);
20292
+ let systemPrompt = "";
20293
+ const filteredMessages = [];
20294
+ for (const m of messages) {
20295
+ 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") : "";
20296
+ if (m.role === "system") {
20297
+ systemPrompt = systemPrompt ? `${systemPrompt}
20298
+
20299
+ ${text}` : text;
20300
+ } else if (m.role === "user" || m.role === "assistant" || m.role === "tool") {
20301
+ filteredMessages.push({
20302
+ role: m.role,
20303
+ text,
20304
+ ...m.tool_call_id ? { toolCallId: m.tool_call_id } : {},
20305
+ ...m.tool_calls?.length ? { toolCalls: m.tool_calls } : {}
20306
+ });
20307
+ }
20308
+ }
20309
+ const coalesced = [];
20310
+ for (const item of filteredMessages) {
20311
+ const last = coalesced[coalesced.length - 1];
20312
+ if (last && last.role === item.role && item.role !== "tool" && !last.toolCalls?.length && !item.toolCalls?.length) {
20313
+ last.text = `${last.text}
20314
+
20315
+ ${item.text}`;
20316
+ } else {
20317
+ coalesced.push({ ...item });
20318
+ }
20319
+ }
20320
+ const chatMessageBuffers = coalesced.map((m) => encodeDevinChatMessage(m));
20321
+ const completionConfig = buildCompletionConfig({ temperature });
20322
+ const modelConfig = Buffer.concat([
20323
+ writeStringField(1, randomUUID2()),
20324
+ writeVarint(2, 1),
20325
+ writeVarint(3, 4)
20326
+ ]);
20327
+ return Buffer.concat([
20328
+ writeMessageField(1, metadata),
20329
+ writeStringField(2, systemPrompt),
20330
+ ...chatMessageBuffers.map((b) => writeMessageField(3, b)),
20331
+ writeVarint(7, 5),
20332
+ writeMessageField(8, completionConfig),
20333
+ ...tools.map((tool) => writeMessageField(10, encodeDevinToolDefinition(tool))),
20334
+ writeMessageField(15, modelConfig),
20335
+ writeStringField(16, randomUUID2()),
20336
+ writeVarint(20, 1),
20337
+ writeStringField(21, model)
20338
+ ]);
20339
+ }
20340
+ function buildDevinConnectFrame(payload, flags = 0) {
20341
+ const header = Buffer.alloc(5);
20342
+ header[0] = flags & 255;
20343
+ header.writeUInt32BE(payload.length, 1);
20344
+ return Buffer.concat([header, payload]);
20345
+ }
20346
+ function parseDevinConnectFrames(buffer3) {
20347
+ const frames = [];
20348
+ let offset = 0;
20349
+ while (offset + 5 <= buffer3.length) {
20350
+ const flags = buffer3[offset];
20351
+ const length = buffer3.readUInt32BE(offset + 1);
20352
+ if (offset + 5 + length > buffer3.length) {
20353
+ break;
20354
+ }
20355
+ const payload = buffer3.subarray(offset + 5, offset + 5 + length);
20356
+ frames.push({ flags, payload });
20357
+ offset += 5 + length;
20358
+ }
20359
+ return {
20360
+ frames,
20361
+ remainder: buffer3.subarray(offset)
20362
+ };
20363
+ }
20364
+ function parseDevinMetadataUsage(metaBytes) {
20365
+ let prompt = 0;
20366
+ let completion;
20367
+ let cacheRead = 0;
20368
+ let cacheWrite = 0;
20369
+ let sawAny = false;
20370
+ let offset = 0;
20371
+ while (offset < metaBytes.length) {
20372
+ let tag = 0;
20373
+ let shift = 0;
20374
+ while (offset < metaBytes.length) {
20375
+ const b = metaBytes[offset++];
20376
+ tag |= (b & 127) << shift;
20377
+ if (!(b & 128)) break;
20378
+ shift += 7;
20379
+ }
20380
+ const fieldNum = tag >>> 3;
20381
+ const wireType = tag & 7;
20382
+ if (wireType === 0) {
20383
+ let val = 0;
20384
+ let s = 0;
20385
+ while (offset < metaBytes.length) {
20386
+ const b = metaBytes[offset++];
20387
+ val |= (b & 127) << s;
20388
+ if (!(b & 128)) break;
20389
+ s += 7;
20390
+ }
20391
+ if (fieldNum === 2) {
20392
+ prompt = val;
20393
+ sawAny = true;
20394
+ } else if (fieldNum === 3) {
20395
+ completion = val;
20396
+ sawAny = true;
20397
+ } else if (fieldNum === 4) {
20398
+ cacheWrite = val;
20399
+ sawAny = true;
20400
+ } else if (fieldNum === 5) {
20401
+ cacheRead = val;
20402
+ sawAny = true;
20403
+ }
20404
+ } else if (wireType === 2) {
20405
+ let len = 0;
20406
+ let s = 0;
20407
+ while (offset < metaBytes.length) {
20408
+ const b = metaBytes[offset++];
20409
+ len |= (b & 127) << s;
20410
+ if (!(b & 128)) break;
20411
+ s += 7;
20412
+ }
20413
+ offset += len;
20414
+ } else {
20415
+ break;
20416
+ }
20417
+ }
20418
+ return sawAny ? { prompt, completion, cacheRead, cacheWrite } : null;
20419
+ }
20420
+ function attachDevinUpstreamFailure(error, failure) {
20421
+ if (failure) {
20422
+ error.devinUpstreamFailure = failure;
20423
+ }
20424
+ return error;
20425
+ }
20426
+ function readDevinUpstreamFailure(error) {
20427
+ if (!error || typeof error !== "object") return void 0;
20428
+ const failure = error.devinUpstreamFailure;
20429
+ if (!failure || typeof failure !== "object") return void 0;
20430
+ if (typeof failure.status !== "number" || !Number.isFinite(failure.status)) {
20431
+ return void 0;
20432
+ }
20433
+ return failure;
20434
+ }
20435
+ function parseDevinConnectTrailer(payload) {
20436
+ const text = payload.toString("utf8").trim();
20437
+ if (!text || text === "{}") return null;
20438
+ try {
20439
+ const parsed = JSON.parse(text);
20440
+ if (!parsed.error) {
20441
+ return new Error(`Devin Connect invalid terminal trailer: ${text}`);
20442
+ }
20443
+ const code = typeof parsed.error.code === "string" ? parsed.error.code : "unknown";
20444
+ const message = typeof parsed.error.message === "string" ? parsed.error.message : "Unknown error";
20445
+ return attachDevinUpstreamFailure(
20446
+ new Error(`Devin Connect upstream error ${code}: ${message}`),
20447
+ // Connect/gRPC 的 resource_exhausted 与 HTTP 429 同义(限流/配额耗尽)。
20448
+ code === "resource_exhausted" ? { status: 429, body: parsed.error } : void 0
20449
+ );
20450
+ } catch {
20451
+ return new Error(`Devin Connect invalid terminal trailer: ${text}`);
20452
+ }
20453
+ }
20454
+ function decodeDevinResponsePayload(payload) {
20455
+ let offset = 0;
20456
+ let content = "";
20457
+ let reasoning = "";
20458
+ let finishReason = null;
20459
+ let usage = null;
20460
+ const events = [];
20461
+ while (offset < payload.length) {
20462
+ let tag = 0;
20463
+ let shift = 0;
20464
+ while (offset < payload.length) {
20465
+ const b = payload[offset++];
20466
+ tag |= (b & 127) << shift;
20467
+ if (!(b & 128)) break;
20468
+ shift += 7;
20469
+ }
20470
+ const fieldNum = tag >>> 3;
20471
+ const wireType = tag & 7;
20472
+ if (wireType === 0) {
20473
+ let val = 0;
20474
+ let s = 0;
20475
+ while (offset < payload.length) {
20476
+ const b = payload[offset++];
20477
+ val |= (b & 127) << s;
20478
+ if (!(b & 128)) break;
20479
+ s += 7;
20480
+ }
20481
+ if (fieldNum === 5) {
20482
+ finishReason = val === 10 ? "tool_calls" : val === 1 || val === 3 ? "length" : "stop";
20483
+ }
20484
+ } else if (wireType === 2) {
20485
+ let len = 0;
20486
+ let s = 0;
20487
+ while (offset < payload.length) {
20488
+ const b = payload[offset++];
20489
+ len |= (b & 127) << s;
20490
+ if (!(b & 128)) break;
20491
+ s += 7;
20492
+ }
20493
+ const valBytes = payload.subarray(offset, offset + len);
20494
+ offset += len;
20495
+ if (fieldNum === 3) {
20496
+ const text = valBytes.toString("utf8");
20497
+ content += text;
20498
+ events.push({ type: "content", text });
20499
+ } else if (fieldNum === 9) {
20500
+ const text = valBytes.toString("utf8");
20501
+ reasoning += text;
20502
+ events.push({ type: "reasoning", text });
20503
+ } else if (fieldNum === 6) {
20504
+ let nestedOffset = 0;
20505
+ let id;
20506
+ let name;
20507
+ let argsDelta;
20508
+ while (nestedOffset < valBytes.length) {
20509
+ let nestedTag = 0;
20510
+ let nestedShift = 0;
20511
+ while (nestedOffset < valBytes.length) {
20512
+ const b = valBytes[nestedOffset++];
20513
+ nestedTag |= (b & 127) << nestedShift;
20514
+ if (!(b & 128)) break;
20515
+ nestedShift += 7;
20516
+ }
20517
+ const nestedField = nestedTag >>> 3;
20518
+ const nestedWire = nestedTag & 7;
20519
+ if (nestedWire !== 2) break;
20520
+ let nestedLength = 0;
20521
+ let lengthShift = 0;
20522
+ while (nestedOffset < valBytes.length) {
20523
+ const b = valBytes[nestedOffset++];
20524
+ nestedLength |= (b & 127) << lengthShift;
20525
+ if (!(b & 128)) break;
20526
+ lengthShift += 7;
20527
+ }
20528
+ const nestedValue = valBytes.subarray(nestedOffset, nestedOffset + nestedLength);
20529
+ nestedOffset += nestedLength;
20530
+ const text = nestedValue.toString("utf8");
20531
+ if (nestedField === 1) id = text;
20532
+ else if (nestedField === 2) name = text;
20533
+ else if (nestedField === 3) argsDelta = (argsDelta ?? "") + text;
20534
+ }
20535
+ if (id !== void 0 && name !== void 0) {
20536
+ events.push({ type: "tool-call-start", id, name });
20537
+ }
20538
+ if (argsDelta !== void 0) {
20539
+ events.push({ type: "tool-call-args", argsDelta, ...id ? { id } : {} });
20540
+ }
20541
+ } else if (fieldNum === 7) {
20542
+ usage = parseDevinMetadataUsage(valBytes);
20543
+ }
20544
+ } else {
20545
+ break;
20546
+ }
20547
+ }
20548
+ return { content, reasoning, finishReason, events, usage };
20549
+ }
20550
+ function createDevinProvider(options) {
20551
+ const { token, model = "swe-2-max", fetchImpl = fetch, tools = [], temperature } = options;
20552
+ return {
20553
+ model,
20554
+ async complete(messages, opts) {
20555
+ const selectedModel = model;
20556
+ const requestPayload = buildGetChatMessageRequest({
20557
+ token,
20558
+ messages,
20559
+ model: selectedModel,
20560
+ tools,
20561
+ temperature
20562
+ });
20563
+ const frame = buildDevinConnectFrame(requestPayload);
20564
+ const response = await fetchImpl(DEVIN_CONNECT_URL, {
20565
+ method: "POST",
20566
+ headers: {
20567
+ "authorization": `Basic ${token}-${token}`,
20568
+ "content-type": "application/connect+proto",
20569
+ "connect-protocol-version": "1"
20570
+ },
20571
+ body: new Uint8Array(frame),
20572
+ signal: opts?.signal
20573
+ });
20574
+ if (!response.ok) {
20575
+ const errText = await response.text().catch(() => "");
20576
+ throw attachDevinUpstreamFailure(
20577
+ new Error(
20578
+ `Devin Connect upstream returned error ${response.status}: ${errText}`
20579
+ ),
20580
+ { status: response.status, body: errText }
20581
+ );
20582
+ }
20583
+ if (!response.body) {
20584
+ throw new Error("Devin Connect response body is null");
20585
+ }
20586
+ let text = "";
20587
+ let reasoning = "";
20588
+ let finishReason = null;
20589
+ let frameUsage = null;
20590
+ const toolCallOrder = [];
20591
+ const toolCallById = /* @__PURE__ */ new Map();
20592
+ let currentToolCallId = null;
20593
+ let buffer3 = Buffer.alloc(0);
20594
+ let sawTrailer = false;
20595
+ const reader = response.body.getReader();
20596
+ try {
20597
+ while (true) {
20598
+ const { done: done4, value } = await reader.read();
20599
+ if (done4) break;
20600
+ buffer3 = Buffer.concat([buffer3, Buffer.from(value)]);
20601
+ const { frames, remainder } = parseDevinConnectFrames(buffer3);
20602
+ buffer3 = Buffer.from(remainder);
20603
+ for (const f of frames) {
20604
+ if (sawTrailer) {
20605
+ throw new Error("Devin Connect received a frame after the terminal trailer");
20606
+ }
20607
+ if (f.flags & 2) {
20608
+ sawTrailer = true;
20609
+ const trailerError = parseDevinConnectTrailer(f.payload);
20610
+ if (trailerError) throw trailerError;
20611
+ continue;
20612
+ }
20613
+ const delta = decodeDevinResponsePayload(f.payload);
20614
+ if (delta.usage?.completion !== void 0) {
20615
+ frameUsage = delta.usage;
20616
+ }
20617
+ text += delta.content;
20618
+ reasoning += delta.reasoning;
20619
+ if (delta.finishReason) finishReason = delta.finishReason;
20620
+ for (const event of delta.events) {
20621
+ if (event.type === "reasoning") {
20622
+ opts?.onReasoningDelta?.(event.text);
20623
+ } else if (event.type === "content") {
20624
+ opts?.onTextDelta?.(event.text);
20625
+ } else if (event.type === "tool-call-start") {
20626
+ const existing = toolCallById.get(event.id);
20627
+ if (existing) {
20628
+ existing.name = event.name;
20629
+ } else {
20630
+ toolCallOrder.push(event.id);
20631
+ toolCallById.set(event.id, {
20632
+ id: event.id,
20633
+ name: event.name,
20634
+ argumentsText: ""
20635
+ });
20636
+ }
20637
+ currentToolCallId = event.id;
20638
+ } else {
20639
+ const targetId = event.id ?? currentToolCallId;
20640
+ const target = targetId ? toolCallById.get(targetId) : void 0;
20641
+ if (target) target.argumentsText += event.argsDelta;
20642
+ }
20643
+ }
20644
+ }
20645
+ }
20646
+ } finally {
20647
+ reader.releaseLock();
20648
+ }
20649
+ if (buffer3.length > 0) {
20650
+ throw new Error("Devin Connect upstream ended with an incomplete frame");
20651
+ }
20652
+ if (!sawTrailer) {
20653
+ throw new Error("Devin Connect upstream ended before the terminal trailer");
20654
+ }
20655
+ const toolCalls = toolCallOrder.map((id) => {
20656
+ const call = toolCallById.get(id);
20657
+ return {
20658
+ id: call.id,
20659
+ type: "function",
20660
+ function: {
20661
+ name: call.name,
20662
+ arguments: call.argumentsText || "{}"
20663
+ }
20664
+ };
20665
+ });
20666
+ if (!text && !reasoning && toolCalls.length === 0) {
20667
+ throw new Error("Devin Connect upstream completed without content or tool calls");
20668
+ }
20669
+ const usage = frameUsage ? {
20670
+ prompt_tokens: frameUsage.prompt + frameUsage.cacheRead,
20671
+ completion_tokens: frameUsage.completion ?? 0,
20672
+ total_tokens: frameUsage.prompt + frameUsage.cacheRead + (frameUsage.completion ?? 0) + frameUsage.cacheWrite,
20673
+ ...frameUsage.cacheRead > 0 ? { prompt_tokens_details: { cached_tokens: frameUsage.cacheRead } } : {},
20674
+ ...frameUsage.cacheWrite > 0 ? { cache_creation_input_tokens: frameUsage.cacheWrite } : {}
20675
+ } : void 0;
20676
+ return {
20677
+ content: text,
20678
+ model: selectedModel,
20679
+ provider: "devin",
20680
+ ...usage ? { usage } : {},
20681
+ ...reasoning ? { reasoning_content: reasoning } : {},
20682
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
20683
+ // The upstream finish event wins whenever it is present. A tool call
20684
+ // cut off by the length limit has to stay "length" instead of being
20685
+ // relabelled "tool_calls", so probes/telemetry and any downstream
20686
+ // consumer of the final finish_reason no longer see a truncated turn
20687
+ // mislabelled as a normal one. localLoop keeps its own truncation
20688
+ // gates and excludes tool-bearing turns from them.
20689
+ finish_reason: finishReason ?? (toolCalls.length > 0 ? "tool_calls" : "stop"),
20690
+ stream_complete: true
20691
+ };
20692
+ }
20693
+ };
20694
+ }
20695
+
20066
20696
  export {
20067
20697
  Option_exports,
20068
20698
  Duration_exports,
@@ -20072,6 +20702,7 @@ export {
20072
20702
  readActionGate,
20073
20703
  evaluateFileWritePolicy,
20074
20704
  summarizeToolArguments,
20705
+ formatToolOverflowMarker,
20075
20706
  LOCAL_AGENT_CONFIG_MISSING_CODE,
20076
20707
  LOCAL_TURN_ABORTED_CODE,
20077
20708
  runLocalAgentTurn,
@@ -20114,5 +20745,7 @@ export {
20114
20745
  shouldUseGeminiNativeToolRoute,
20115
20746
  buildGeminiGenerateContentRequest,
20116
20747
  resolveAntigravityFinishReason,
20117
- fetchAntigravityCloudCodeCompletion
20748
+ fetchAntigravityCloudCodeCompletion,
20749
+ readDevinUpstreamFailure,
20750
+ createDevinProvider
20118
20751
  };