nolo-cli 0.89.0-alpha.1 → 0.90.0-alpha.1

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 (132) hide show
  1. package/README.md +2 -2
  2. package/{_executeModel-I3XRMAJ2.js → _executeModel-W26HVI75.js} +38 -38
  3. package/{action-7GHFPDSQ.js → action-6DXQGJMX.js} +7 -7
  4. package/{addContentAction-ZNVB2NOV.js → addContentAction-I7VX5SAC.js} +5 -5
  5. package/{addDialogAgentAction-CIDFWATM.js → addDialogAgentAction-OJSFV7DZ.js} +4 -4
  6. package/{agentDeleteCommand-DCTG26JW.js → agentDeleteCommand-XNFWCKBH.js} +24 -23
  7. package/{agentEmailCommands-MRRHBLDQ.js → agentEmailCommands-W3X3EJ3V.js} +50 -49
  8. package/{agentGrantCommands-R3VQEZJR.js → agentGrantCommands-YW6PQAQ2.js} +2 -2
  9. package/{agentListCommands-CUE46CSP.js → agentListCommands-DFWFU6XO.js} +32 -25
  10. package/{agentMachineCommands-FYDEKBIO.js → agentMachineCommands-LMFOAEL4.js} +24 -23
  11. package/{agentProviderCommands-X3FA6BUM.js → agentProviderCommands-ZBYHGTGY.js} +1 -1
  12. package/{agentPullCommand-U73W5IBM.js → agentPullCommand-GLOOXJ2E.js} +2 -2
  13. package/{agentRecordCommands-P2MSNP7R.js → agentRecordCommands-FVVVCQFM.js} +48 -47
  14. package/{agentRunCommand-QJGP7JEN.js → agentRunCommand-HTBVIBGV.js} +49 -48
  15. package/{agentRunControl-T44MESII.js → agentRunControl-XLGD3UZ5.js} +1 -1
  16. package/{agentRuntimeLocal-T43UNWAY.js → agentRuntimeLocal-2JFG4HDU.js} +20 -19
  17. package/{agentSlice-7GDS5Q2S.js → agentSlice-ZNLGFUB5.js} +5 -5
  18. package/{appDeleteCommands-YBKY3VEI.js → appDeleteCommands-2UN4N2NR.js} +25 -24
  19. package/{appDeployCommands-EBC76HO4.js → appDeployCommands-37D74KRR.js} +25 -24
  20. package/{appDeployStatusCommands-WXRC5KEK.js → appDeployStatusCommands-QBLWL2IA.js} +25 -24
  21. package/{appGetCommands-VZZQEDOV.js → appGetCommands-6KXIDF2T.js} +25 -24
  22. package/{appListCommands-HYSPVQ77.js → appListCommands-G2WFGEWQ.js} +25 -24
  23. package/{authCommand-E4GDVKMW.js → authCommand-V2DJ7DB7.js} +84 -18
  24. package/{authCommands-VOTT6XWX.js → authCommands-RGOGCPP6.js} +2 -2
  25. package/{builtinSkillRegistry-5SYVTS6Z.js → builtinSkillRegistry-WBGYKIAZ.js} +5 -5
  26. package/{chatQueueReduxAdapter-CXEWIDFZ.js → chatQueueReduxAdapter-XCJHIY3R.js} +17 -17
  27. package/{chunk-P3AS5IPM.js → chunk-2ADBVBEM.js} +3 -2
  28. package/{chunk-GRJTR4PU.js → chunk-2AYMFHUG.js} +4 -4
  29. package/{chunk-UO66QKGI.js → chunk-2F4VYGFW.js} +2 -2
  30. package/{chunk-LEYH5NOH.js → chunk-3CMTBX3X.js} +4 -4
  31. package/{chunk-GXWEF4IZ.js → chunk-3CR2LC6X.js} +1 -1
  32. package/{chunk-ZKGIAM7I.js → chunk-3R5PH4IP.js} +1 -1
  33. package/{chunk-VW3YGKWR.js → chunk-4BYPU626.js} +294 -203
  34. package/{chunk-PHDKTASK.js → chunk-4DRWWIOL.js} +1 -1
  35. package/{chunk-BNMZ7QUV.js → chunk-576IMUGH.js} +1 -1
  36. package/{chunk-AYT2OKNM.js → chunk-5DFFKASO.js} +3 -3
  37. package/{chunk-Q246OUG5.js → chunk-5NMZNPTN.js} +5 -5
  38. package/{chunk-5XTOKQLW.js → chunk-5UTFL4QJ.js} +6 -2
  39. package/{chunk-6RCZYDDC.js → chunk-5V4NJHRM.js} +6 -6
  40. package/chunk-5ZUL4CUO.js +10 -0
  41. package/{chunk-US463UAD.js → chunk-6BEA566T.js} +2 -2
  42. package/{chunk-UINEAQ2R.js → chunk-6D6VBVEW.js} +1 -1
  43. package/{chunk-JC2WQS66.js → chunk-7MYYE7WX.js} +20 -16
  44. package/{chunk-3T4PRBHV.js → chunk-A2C4AKKM.js} +1 -1
  45. package/{chunk-6ZC5KPXV.js → chunk-AQZRTHDZ.js} +903 -40
  46. package/{chunk-UWMQ6FPM.js → chunk-ASGDO77C.js} +118 -1
  47. package/{chunk-2KDR4CWE.js → chunk-BYMV6QZG.js} +24 -1
  48. package/{chunk-XCSSFPTB.js → chunk-CLI4LFSM.js} +1 -1
  49. package/{chunk-HH65VA5U.js → chunk-CPH3W5A7.js} +15 -3
  50. package/{chunk-TGRQUFLU.js → chunk-DNQPPRHY.js} +1 -1
  51. package/{chunk-2XEVK4BT.js → chunk-DPQ2WVBY.js} +1 -1
  52. package/{chunk-OCL2YCAU.js → chunk-F2CGG72C.js} +40 -40
  53. package/{chunk-S6STPUMG.js → chunk-FQYMLZ6C.js} +5 -5
  54. package/{chunk-BJIRLHJR.js → chunk-GII32WZW.js} +1 -0
  55. package/{chunk-VARZWSKW.js → chunk-GRYGRGPS.js} +3 -3
  56. package/{chunk-L2VNQQ7M.js → chunk-HMEMJ7GH.js} +364 -24
  57. package/{chunk-OZX2IPKM.js → chunk-HQCSU3DI.js} +1 -1
  58. package/{chunk-VQD6BTML.js → chunk-HYZHJ5GW.js} +3 -3
  59. package/{chunk-OAJRZ35U.js → chunk-IIKPWSPX.js} +1 -1
  60. package/{chunk-W7PGACND.js → chunk-JBBZ5KUM.js} +10 -10
  61. package/{chunk-KC5FAHVS.js → chunk-JEDZAO7L.js} +1 -1
  62. package/{chunk-LSV2BOJL.js → chunk-JTK3TJYV.js} +1 -1
  63. package/{chunk-X77EN2BJ.js → chunk-K7M3MWCE.js} +2 -2
  64. package/{chunk-OHUU52T3.js → chunk-L2ICPOAL.js} +1 -1
  65. package/{chunk-EVBFYPDC.js → chunk-MC4XLIJ7.js} +6 -2
  66. package/{chunk-DS3SQTDT.js → chunk-MJHQ3NRV.js} +1 -1
  67. package/{chunk-Q4KVAB6L.js → chunk-N3OAPEZE.js} +28 -9
  68. package/{chunk-T4F2EQGN.js → chunk-ND2J3NRB.js} +2 -2
  69. package/{chunk-IMDA4FW4.js → chunk-NFMHIUY3.js} +61 -46
  70. package/{chunk-JITSBA52.js → chunk-PH5J5VUY.js} +2 -2
  71. package/{chunk-FMODTASJ.js → chunk-Q5FJJ6XI.js} +1 -7
  72. package/{chunk-JYYZCK2Z.js → chunk-QFMFJZLO.js} +1 -1
  73. package/{chunk-WSOMSDQB.js → chunk-QHETQ3KI.js} +35 -1
  74. package/{chunk-IZAWJCG7.js → chunk-RZANZZL2.js} +1 -1
  75. package/{chunk-SPAQ4PVV.js → chunk-SAFZABH7.js} +1 -1
  76. package/{chunk-EXWOCYCR.js → chunk-SMZSWB44.js} +10 -5
  77. package/{chunk-HJKGQPYF.js → chunk-TL6L5XUT.js} +1 -1
  78. package/{chunk-4FRNB4ZG.js → chunk-TVNI5FLG.js} +4 -4
  79. package/{chunk-5EJZGJS2.js → chunk-UA5S3LQQ.js} +3 -3
  80. package/{chunk-Y2IFJ7VM.js → chunk-UTCCPWB2.js} +3 -3
  81. package/{chunk-KT6LENVP.js → chunk-VHJLQHPQ.js} +2 -2
  82. package/{chunk-6H7GN3JL.js → chunk-VRLI2WNW.js} +10 -1
  83. package/{chunk-23RQKXP6.js → chunk-WS22FPWT.js} +1 -1
  84. package/{chunk-NVHJWYUO.js → chunk-WXPVOQD7.js} +35 -33
  85. package/{chunk-MFW4BGJS.js → chunk-XKQJJK4F.js} +1 -1
  86. package/{chunk-GIG262ZG.js → chunk-XMGHGEN6.js} +1 -1
  87. package/{chunk-IO7DYRPW.js → chunk-XTUY5EL4.js} +16 -12
  88. package/{chunk-OKCTLCKS.js → chunk-YOXYA2GU.js} +1 -1
  89. package/{chunk-ZIHJVHFH.js → chunk-Z33ARZCP.js} +1 -1
  90. package/{chunk-ZSG2AQU4.js → chunk-ZAB3A45K.js} +62 -11
  91. package/{chunk-YZHP76TR.js → chunk-ZBT3WNBK.js} +1 -1
  92. package/{contentThunks-Y2ACIFDB.js → contentThunks-VURN3DFW.js} +18 -18
  93. package/{createAgentAutomationAction-TNE3QMJR.js → createAgentAutomationAction-QZAAY77R.js} +18 -18
  94. package/{createDialogAction-BMGHBTQB.js → createDialogAction-CHGXVTAC.js} +20 -20
  95. package/{createPageAction-FFNIZPIS.js → createPageAction-IOGAFIN7.js} +18 -18
  96. package/{dbSlice-4CUQE35F.js → dbSlice-YXQ6RYIH.js} +4 -4
  97. package/{dialogCommands-3JC3BIXC.js → dialogCommands-XREAP6WQ.js} +26 -25
  98. package/{dialogSlice-3E7Z7HZV.js → dialogSlice-DOPGWGS4.js} +17 -17
  99. package/{docCreateCommands-6LNQLCTA.js → docCreateCommands-3PYZGSCL.js} +24 -23
  100. package/{docDeleteCommands-ZJOAPWZS.js → docDeleteCommands-3Y6MU44Q.js} +25 -24
  101. package/{docReadCommands-LJTRSBG6.js → docReadCommands-UBANMAFR.js} +24 -23
  102. package/{docStore-R47ABXBB.js → docStore-SYYFBENY.js} +5 -5
  103. package/{docUpdateCommands-7P3QF3N2.js → docUpdateCommands-4GK2X6BN.js} +24 -23
  104. package/{getPricing-TV6ZB7ES.js → getPricing-F2C65RIX.js} +3 -3
  105. package/{handleSendMessageAction-FFYOGXAO.js → handleSendMessageAction-NPVTY2GE.js} +17 -17
  106. package/index.js +81 -81
  107. package/{machineCommands-FN5GGQV3.js → machineCommands-I66X2XB7.js} +47 -46
  108. package/{machineWsRunDispatch-H47IA7ZT.js → machineWsRunDispatch-W4FVBOUM.js} +47 -46
  109. package/{memberThunks-N35XAOC6.js → memberThunks-5T4J6KXQ.js} +5 -5
  110. package/{models-CMXFDBQH.js → models-WW7VFNXB.js} +2 -2
  111. package/{offlineMarxistsAgentCommand-GEH6SNNA.js → offlineMarxistsAgentCommand-JEWCIAWM.js} +1 -1
  112. package/package.json +1 -1
  113. package/{providerPresetApply-D2GGHPI7.js → providerPresetApply-OCWWKBSD.js} +6 -6
  114. package/{providerRegistry-MU6C4ABD.js → providerRegistry-ZJQU7AJ7.js} +6 -6
  115. package/{read-2PV4PN2E.js → read-M2Q6WEKB.js} +3 -3
  116. package/{readDocTool-FGK5XGAW.js → readDocTool-T37P3YPB.js} +1 -1
  117. package/{readlineWorkspace-NXKHYZEU.js → readlineWorkspace-VY5AMOGR.js} +123 -91
  118. package/{removeDialogAgentAction-O2POGBOE.js → removeDialogAgentAction-HB3JBVAI.js} +7 -7
  119. package/{runAgentClientLoop-CEBV5UPD.js → runAgentClientLoop-3NDADLVE.js} +36 -36
  120. package/{setDialogExtraReferencesAction-KPSVVY3C.js → setDialogExtraReferencesAction-4XLHRV37.js} +5 -5
  121. package/{setPrimaryDialogAgentAction-RMJETONI.js → setPrimaryDialogAgentAction-C3JOFC4W.js} +7 -7
  122. package/{settingSlice-I6MTTNDX.js → settingSlice-CZRURSTH.js} +6 -6
  123. package/{spaceCommands-JHT4ALCQ.js → spaceCommands-ENYCUUZH.js} +24 -23
  124. package/{streamAgentChatTurn-SFCZP4GY.js → streamAgentChatTurn-634OFUSR.js} +44 -42
  125. package/{switchDialogAgentAction-OQSGWVQQ.js → switchDialogAgentAction-C6KVUKJP.js} +4 -4
  126. package/{tableCommands-SUNTHAYX.js → tableCommands-O6NWHFKV.js} +1 -1
  127. package/{toolApiClient-VGYUB4P5.js → toolApiClient-7PSIFQPJ.js} +2 -2
  128. package/{tools-K3YOTESV.js → tools-ILBLCF7D.js} +33 -33
  129. package/tuiSummaryLlmCaller-LFUBZKXK.js +127 -0
  130. package/{updateCommands-Y363MC3L.js → updateCommands-2M74UL7P.js} +2 -2
  131. package/{updateDialogTitleAction-CSPKYQRO.js → updateDialogTitleAction-RKFET73N.js} +38 -21
  132. package/tuiSummaryLlmCaller-T2OA5ZVB.js +0 -116
@@ -8,18 +8,19 @@ import {
8
8
  readSseFrames,
9
9
  streamSseDataValues,
10
10
  throwIfChatCompletionStreamFailed
11
- } from "./chunk-EXWOCYCR.js";
11
+ } from "./chunk-SMZSWB44.js";
12
12
  import {
13
13
  DEVIN_CONNECT_URL
14
- } from "./chunk-FMODTASJ.js";
14
+ } from "./chunk-Q5FJJ6XI.js";
15
15
  import {
16
16
  clipToolText,
17
17
  hasImageInRuntimeMessages,
18
+ resolveAgentContextWindow,
18
19
  resolveAgentImageInputSupport,
19
20
  resolveHistoricalToolContentCap,
20
21
  resolveToolOutputProfile,
21
22
  stripImagePartsFromMessages
22
- } from "./chunk-WSOMSDQB.js";
23
+ } from "./chunk-QHETQ3KI.js";
23
24
  import {
24
25
  downgradeUnparsableToolCalls,
25
26
  hasParsableObjectArguments,
@@ -43,7 +44,7 @@ import {
43
44
  requiresBareImageUrl,
44
45
  resolveToolGuidedSections,
45
46
  toBareImageUrlMessages
46
- } from "./chunk-Q4KVAB6L.js";
47
+ } from "./chunk-N3OAPEZE.js";
47
48
  import {
48
49
  convertMessagesToResponsesInput,
49
50
  extractReasoningFromResponseOutput,
@@ -67,16 +68,16 @@ import {
67
68
  parseNoloWorkspaceToolArguments,
68
69
  readTextStreamUpToChars,
69
70
  resolveNoloDialogInput
70
- } from "./chunk-OKCTLCKS.js";
71
+ } from "./chunk-YOXYA2GU.js";
71
72
  import {
72
73
  getAntigravityUserAgent,
73
74
  readAntigravityProjectId,
74
75
  resolveAntigravityCloudCodeBaseUrl
75
- } from "./chunk-DS3SQTDT.js";
76
+ } from "./chunk-MJHQ3NRV.js";
76
77
  import {
77
78
  buildProviderAuthHeaders,
78
79
  buildProviderExecutionPlan
79
- } from "./chunk-X77EN2BJ.js";
80
+ } from "./chunk-K7M3MWCE.js";
80
81
  import {
81
82
  buildDialogFallbackTitleFromUserInput
82
83
  } from "./chunk-2MBTWINN.js";
@@ -90,7 +91,7 @@ import {
90
91
  resolveEmptyAssistantFallbackMessage,
91
92
  resolveEmptyAssistantOutcome,
92
93
  resolveTruncatedReasoningTailLog
93
- } from "./chunk-OCL2YCAU.js";
94
+ } from "./chunk-F2CGG72C.js";
94
95
  import {
95
96
  COMPACTION_SUMMARY_SCHEMA_VERSION,
96
97
  COMPACTION_SUMMARY_SYSTEM_PROMPT,
@@ -109,7 +110,7 @@ import {
109
110
  resolveCompressionTriggerRatio,
110
111
  truncateToolOutputForContext,
111
112
  withProviderCallTimingFields
112
- } from "./chunk-KT6LENVP.js";
113
+ } from "./chunk-VHJLQHPQ.js";
113
114
  import {
114
115
  estimateTokenCount
115
116
  } from "./chunk-PSCNXBYA.js";
@@ -12201,8 +12202,208 @@ function summarizeToolArguments(toolName, rawArgs) {
12201
12202
  );
12202
12203
  }
12203
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
+
12204
12405
  // packages/agent-runtime/leafFinalHandoff.ts
12205
- 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.`;
12206
12407
 
12207
12408
  // packages/agent-runtime/contextBlockScope.ts
12208
12409
  var isContextBlockScope = (value) => {
@@ -12557,191 +12758,6 @@ async function maybeAutoCompactLocalHistory(args2) {
12557
12758
  }
12558
12759
  }
12559
12760
 
12560
- // packages/agent-runtime/progressGuard.ts
12561
- var DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS = 5;
12562
- var DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS = 8;
12563
- function sortJsonKeys(obj) {
12564
- if (obj === null || typeof obj !== "object") return obj;
12565
- if (Array.isArray(obj)) return obj.map(sortJsonKeys);
12566
- const sorted = {};
12567
- for (const key of Object.keys(obj).sort()) {
12568
- sorted[key] = sortJsonKeys(obj[key]);
12569
- }
12570
- return sorted;
12571
- }
12572
- function normalizeToolArguments(rawArgs) {
12573
- if (typeof rawArgs !== "string") {
12574
- try {
12575
- return JSON.stringify(sortJsonKeys(rawArgs ?? ""));
12576
- } catch {
12577
- return String(rawArgs ?? "");
12578
- }
12579
- }
12580
- const trimmed = rawArgs.trim();
12581
- if (!trimmed) return "";
12582
- try {
12583
- const parsed = JSON.parse(trimmed);
12584
- return JSON.stringify(sortJsonKeys(parsed));
12585
- } catch {
12586
- return trimmed;
12587
- }
12588
- }
12589
- function extractNormalizedContentText(content) {
12590
- if (typeof content === "string") return content.trim();
12591
- if (!Array.isArray(content)) return "";
12592
- return content.map((part) => {
12593
- if (part?.type === "text") return String(part.text ?? "").trim();
12594
- if (part?.type === "image_url") return `[img:${part.image_url?.url ?? ""}]`;
12595
- return "";
12596
- }).filter(Boolean).join("\n");
12597
- }
12598
- function buildToolCallsSignature(toolCalls) {
12599
- if (!toolCalls || toolCalls.length === 0) return "";
12600
- return toolCalls.map(
12601
- (tc) => `${tc.function?.name ?? ""}:${normalizeToolArguments(tc.function?.arguments)}`
12602
- ).join(";;");
12603
- }
12604
- function buildAssistantActionFingerprint(result4) {
12605
- const content = extractNormalizedContentText(result4.content);
12606
- const reasoning = typeof result4.reasoning_content === "string" ? result4.reasoning_content.trim() : "";
12607
- let toolCallsSig = buildToolCallsSignature(result4.tool_calls);
12608
- let hasToolCalls = Array.isArray(result4.tool_calls) && result4.tool_calls.length > 0;
12609
- if (!toolCallsSig && Array.isArray(result4.output) && result4.output.length > 0) {
12610
- const blocksToolCalls = result4.output.filter(
12611
- (b) => b.type === "toolCall"
12612
- ).map((b) => b.toolCall);
12613
- if (blocksToolCalls.length > 0) {
12614
- toolCallsSig = buildToolCallsSignature(blocksToolCalls);
12615
- hasToolCalls = true;
12616
- }
12617
- }
12618
- const hasNonEmptyText = content.length > 0 || reasoning.length > 0;
12619
- const fingerprint = `${content}##${reasoning}##${toolCallsSig}`;
12620
- return {
12621
- fingerprint,
12622
- hasNonEmptyText,
12623
- hasToolCalls,
12624
- toolCallsSignature: toolCallsSig
12625
- };
12626
- }
12627
- function buildToolResultsSignature(toolExecutions) {
12628
- if (toolExecutions.length === 0) return "";
12629
- return toolExecutions.map((exec) => {
12630
- const contentStr = typeof exec.content === "string" ? exec.content.trim() : "";
12631
- const metaStr = exec.metadata ? JSON.stringify(sortJsonKeys(exec.metadata)) : "";
12632
- return `${exec.toolName}:${contentStr}:${metaStr}`;
12633
- }).join(";;");
12634
- }
12635
- function resolveProgressGuardConfig(options, env = typeof process !== "undefined" ? process.env : {}) {
12636
- const envDisabled = env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "true" || env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "1";
12637
- const disabled = options?.disabled ?? envDisabled ?? false;
12638
- const parsePositiveInt = (val, fallback) => {
12639
- if (typeof val === "number" && Number.isFinite(val) && val >= 1) {
12640
- return Math.floor(val);
12641
- }
12642
- if (typeof val === "string") {
12643
- const parsed = parseInt(val, 10);
12644
- if (Number.isFinite(parsed) && parsed >= 1) {
12645
- return parsed;
12646
- }
12647
- }
12648
- return fallback;
12649
- };
12650
- const maxConsecutiveIdenticalRounds = parsePositiveInt(
12651
- options?.maxConsecutiveIdenticalRounds ?? env.NOLO_LOOP_MAX_IDENTICAL_ROUNDS,
12652
- DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS
12653
- );
12654
- const maxConsecutiveStagnantToolRounds = parsePositiveInt(
12655
- options?.maxConsecutiveStagnantToolRounds ?? env.NOLO_LOOP_MAX_STAGNANT_TOOL_ROUNDS,
12656
- DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS
12657
- );
12658
- return {
12659
- disabled,
12660
- maxConsecutiveIdenticalRounds,
12661
- maxConsecutiveStagnantToolRounds
12662
- };
12663
- }
12664
- var LocalLoopProgressGuard = class {
12665
- config;
12666
- lastAssistantFingerprint = null;
12667
- lastAssistantHasNonEmptyText = false;
12668
- consecutiveIdenticalCount = 0;
12669
- lastToolCallsSignature = null;
12670
- lastToolResultsSignature = null;
12671
- consecutiveStagnantToolCount = 0;
12672
- constructor(config, env) {
12673
- this.config = resolveProgressGuardConfig(config, env);
12674
- }
12675
- /**
12676
- * 在 LLM 返回 assistant 响应后调用。
12677
- * 仅在纯文本/无工具调用且实质文本相同达到阈值时直接熔断;
12678
- * 若存在工具调用,则不在此处熔断,留待工具执行后结合工具结果综合判定。
12679
- */
12680
- observeAssistantResponse(result4) {
12681
- if (this.config.disabled) return { action: "continue" };
12682
- const { fingerprint, hasNonEmptyText, hasToolCalls } = buildAssistantActionFingerprint(result4);
12683
- if (this.lastAssistantFingerprint !== null && this.lastAssistantFingerprint === fingerprint) {
12684
- this.consecutiveIdenticalCount += 1;
12685
- if (!hasToolCalls && hasNonEmptyText && this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
12686
- return {
12687
- action: "stall",
12688
- reason: "repetition_loop",
12689
- detail: `Consecutive identical text-only assistant response for ${this.consecutiveIdenticalCount} rounds.`,
12690
- consecutiveRounds: this.consecutiveIdenticalCount
12691
- };
12692
- }
12693
- } else {
12694
- this.lastAssistantFingerprint = fingerprint;
12695
- this.lastAssistantHasNonEmptyText = hasNonEmptyText;
12696
- this.consecutiveIdenticalCount = 1;
12697
- }
12698
- return { action: "continue" };
12699
- }
12700
- /**
12701
- * 在本轮所有工具执行完毕后调用,检查是否陷入停滞死循环。
12702
- * 只有当工具返回内容与元数据完全无变化时才计入无进展 streak;
12703
- * 一旦工具结果发生变化(如合法轮询状态推进),立即重置 identical streak,确保绝不误杀正常长任务。
12704
- */
12705
- observeToolExecution(toolCalls, toolResults) {
12706
- if (this.config.disabled) return { action: "continue" };
12707
- if (!toolCalls || toolCalls.length === 0) return { action: "continue" };
12708
- const toolCallsSig = buildToolCallsSignature(toolCalls);
12709
- const toolResultsSig = buildToolResultsSignature(toolResults);
12710
- const toolCallsUnchanged = this.lastToolCallsSignature !== null && this.lastToolCallsSignature === toolCallsSig;
12711
- const toolResultsUnchanged = this.lastToolResultsSignature !== null && this.lastToolResultsSignature === toolResultsSig;
12712
- if (toolCallsUnchanged && toolResultsUnchanged) {
12713
- this.consecutiveStagnantToolCount += 1;
12714
- if (this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
12715
- return {
12716
- action: "stall",
12717
- reason: "repetition_loop",
12718
- detail: `Consecutive identical assistant response with unchanged tool results for ${this.consecutiveIdenticalCount} rounds.`,
12719
- consecutiveRounds: this.consecutiveIdenticalCount
12720
- };
12721
- }
12722
- if (this.consecutiveStagnantToolCount >= this.config.maxConsecutiveStagnantToolRounds) {
12723
- return {
12724
- action: "stall",
12725
- reason: "stagnant_tool_calls",
12726
- detail: `Consecutive stagnant tool calls with unchanged results for ${this.consecutiveStagnantToolCount} rounds.`,
12727
- consecutiveRounds: this.consecutiveStagnantToolCount
12728
- };
12729
- }
12730
- } else {
12731
- this.lastToolCallsSignature = toolCallsSig;
12732
- this.lastToolResultsSignature = toolResultsSig;
12733
- this.consecutiveStagnantToolCount = 1;
12734
- if (!toolResultsUnchanged) {
12735
- this.consecutiveIdenticalCount = 1;
12736
- }
12737
- }
12738
- return { action: "continue" };
12739
- }
12740
- };
12741
- function createLocalLoopProgressGuard(config, env) {
12742
- return new LocalLoopProgressGuard(config, env);
12743
- }
12744
-
12745
12761
  // packages/agent-runtime/localLoop.ts
12746
12762
  var LOOP_TIMING_ENABLED = typeof process !== "undefined" && process.env?.NOLO_LOOP_TIMING === "1";
12747
12763
  var LOOP_TIMING_FILE = typeof process !== "undefined" ? process.env?.NOLO_LOOP_TIMING_FILE : void 0;
@@ -13047,10 +13063,10 @@ var TOOL_METADATA_KEYS = [
13047
13063
  "pasteId",
13048
13064
  "source"
13049
13065
  ];
13050
- function trimHistoryToContextBudget(history, model) {
13066
+ function trimHistoryToContextBudget(history, model, contextWindowOverride) {
13051
13067
  if (history.length === 0) return { history, droppedCount: 0 };
13052
13068
  const { rawMessageBudget } = planContextUsage({
13053
- contextWindow: getModelContextWindow(model ?? ""),
13069
+ contextWindow: contextWindowOverride ?? getModelContextWindow(model ?? ""),
13054
13070
  summaryTokens: 0,
13055
13071
  // localLoop 没有 web 端的负载分档器;medium 是中性默认值,
13056
13072
  // 不为了省几个 token 在这里复制一份分类逻辑。
@@ -13541,7 +13557,7 @@ async function runLocalAgentTurn(input) {
13541
13557
  }
13542
13558
  return resolvedProvider;
13543
13559
  };
13544
- const contextWindow = getModelContextWindow(agentConfig.model ?? "");
13560
+ const contextWindow = resolveAgentContextWindow(agentConfig);
13545
13561
  const compressionTriggerRatio = resolveCompressionTriggerRatio(contextWindow);
13546
13562
  let realContextUsagePercent;
13547
13563
  if (input.continueDialogId && typeof input.adapter.loadLastContextUsage === "function") {
@@ -13583,6 +13599,7 @@ async function runLocalAgentTurn(input) {
13583
13599
  history,
13584
13600
  model: agentConfig.model,
13585
13601
  resolveProvider: resolveProviderOnce,
13602
+ contextWindow,
13586
13603
  realContextUsagePercent
13587
13604
  });
13588
13605
  history = compacted.history;
@@ -13592,7 +13609,7 @@ async function runLocalAgentTurn(input) {
13592
13609
  console.warn("[localLoop] auto-compaction unexpected error:", error);
13593
13610
  }
13594
13611
  loopTimingMark("maybeAutoCompactLocalHistory", 0);
13595
- const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model);
13612
+ const trimmedHistory = trimHistoryToContextBudget(history, agentConfig.model, contextWindow);
13596
13613
  if (trimmedHistory.droppedCount > 0) {
13597
13614
  history = trimmedHistory.history;
13598
13615
  }
@@ -13679,6 +13696,7 @@ async function runLocalAgentTurn(input) {
13679
13696
  ],
13680
13697
  model: agentConfig.model,
13681
13698
  resolveProvider: resolveProviderOnce,
13699
+ contextWindow,
13682
13700
  realContextUsagePercent: ratio
13683
13701
  });
13684
13702
  if (compacted.usage) {
@@ -13947,6 +13965,7 @@ ${reasoningTailLog}
13947
13965
  const startedAt = Date.now();
13948
13966
  loopTimingMark("toolCallStart", round);
13949
13967
  const argumentsPreview = summarizeToolArguments(toolName, toolCall.function.arguments);
13968
+ const argumentsFingerprint = buildToolArgumentsFingerprint(toolCall.function.arguments);
13950
13969
  emitLoopEvent(
13951
13970
  observationBoundary,
13952
13971
  {
@@ -13955,7 +13974,8 @@ ${reasoningTailLog}
13955
13974
  toolCallId: toolCall.id,
13956
13975
  toolName,
13957
13976
  atMs: startedAt,
13958
- ...argumentsPreview ? { argumentsPreview } : {}
13977
+ ...argumentsPreview ? { argumentsPreview } : {},
13978
+ ...argumentsFingerprint ? { argumentsFingerprint } : {}
13959
13979
  },
13960
13980
  {
13961
13981
  type: "tool-call",
@@ -19353,7 +19373,7 @@ function buildLoadSkillExecutor(args2) {
19353
19373
  const { resolveSkillByName } = await import("./skillDiscovery-CYUCJMAG.js");
19354
19374
  const resolved = resolveSkillByName(args2.cwd, name);
19355
19375
  if (!resolved) {
19356
- const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-5SYVTS6Z.js");
19376
+ const { resolveBuiltinSkillByName } = await import("./builtinSkillRegistry-WBGYKIAZ.js");
19357
19377
  const builtin = resolveBuiltinSkillByName(name);
19358
19378
  if (builtin) {
19359
19379
  return {
@@ -20332,6 +20352,62 @@ function parseDevinConnectFrames(buffer3) {
20332
20352
  remainder: buffer3.subarray(offset)
20333
20353
  };
20334
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
+ }
20335
20411
  function parseDevinConnectTrailer(payload) {
20336
20412
  const text = payload.toString("utf8").trim();
20337
20413
  if (!text || text === "{}") return null;
@@ -20352,6 +20428,7 @@ function decodeDevinResponsePayload(payload) {
20352
20428
  let content = "";
20353
20429
  let reasoning = "";
20354
20430
  let finishReason = null;
20431
+ let usage = null;
20355
20432
  const events = [];
20356
20433
  while (offset < payload.length) {
20357
20434
  let tag = 0;
@@ -20433,15 +20510,17 @@ function decodeDevinResponsePayload(payload) {
20433
20510
  if (argsDelta !== void 0) {
20434
20511
  events.push({ type: "tool-call-args", argsDelta, ...id ? { id } : {} });
20435
20512
  }
20513
+ } else if (fieldNum === 7) {
20514
+ usage = parseDevinMetadataUsage(valBytes);
20436
20515
  }
20437
20516
  } else {
20438
20517
  break;
20439
20518
  }
20440
20519
  }
20441
- return { content, reasoning, finishReason, events };
20520
+ return { content, reasoning, finishReason, events, usage };
20442
20521
  }
20443
20522
  function createDevinProvider(options) {
20444
- const { token, model = "swe-2", fetchImpl = fetch, tools = [], temperature } = options;
20523
+ const { token, model = "swe-2-max", fetchImpl = fetch, tools = [], temperature } = options;
20445
20524
  return {
20446
20525
  model,
20447
20526
  async complete(messages, opts) {
@@ -20476,6 +20555,7 @@ function createDevinProvider(options) {
20476
20555
  let text = "";
20477
20556
  let reasoning = "";
20478
20557
  let finishReason = null;
20558
+ let frameUsage = null;
20479
20559
  const toolCallOrder = [];
20480
20560
  const toolCallById = /* @__PURE__ */ new Map();
20481
20561
  let currentToolCallId = null;
@@ -20500,6 +20580,9 @@ function createDevinProvider(options) {
20500
20580
  continue;
20501
20581
  }
20502
20582
  const delta = decodeDevinResponsePayload(f.payload);
20583
+ if (delta.usage?.completion !== void 0) {
20584
+ frameUsage = delta.usage;
20585
+ }
20503
20586
  text += delta.content;
20504
20587
  reasoning += delta.reasoning;
20505
20588
  if (delta.finishReason) finishReason = delta.finishReason;
@@ -20552,10 +20635,18 @@ function createDevinProvider(options) {
20552
20635
  if (!text && !reasoning && toolCalls.length === 0) {
20553
20636
  throw new Error("Devin Connect upstream completed without content or tool calls");
20554
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;
20555
20645
  return {
20556
20646
  content: text,
20557
20647
  model: selectedModel,
20558
20648
  provider: "devin",
20649
+ ...usage ? { usage } : {},
20559
20650
  ...reasoning ? { reasoning_content: reasoning } : {},
20560
20651
  ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
20561
20652
  // The upstream finish event wins whenever it is present. A tool call
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  patch,
6
6
  read
7
- } from "./chunk-5EJZGJS2.js";
7
+ } from "./chunk-UA5S3LQQ.js";
8
8
  import {
9
9
  DEVICE_LOCAL_OWNER_ID,
10
10
  isDeviceLocalSpaceBody
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  fetchReferenceContents,
3
3
  resolveReferenceAssets
4
- } from "./chunk-JC2WQS66.js";
4
+ } from "./chunk-7MYYE7WX.js";
5
5
 
6
6
  // packages/ai/agent/fetchAgentContexts.ts
7
7
  async function fetchAgentContexts(references, dispatch) {