nolo-cli 0.67.0 → 0.68.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/{_executeModel-C5K4UL5I.js → _executeModel-XCNYHC6S.js} +13 -13
  2. package/{agentDeleteCommand-7RESZDRC.js → agentDeleteCommand-Z3DTLQEG.js} +5 -5
  3. package/{agentEmailCommands-KES5FG2E.js → agentEmailCommands-DFK2MIXR.js} +14 -14
  4. package/{agentListCommands-VFBLREFU.js → agentListCommands-FSX7RY7U.js} +5 -5
  5. package/{agentMachineCommands-UJ77TKWZ.js → agentMachineCommands-FYPV45TJ.js} +6 -6
  6. package/{agentRecordCommands-MZBPYUGL.js → agentRecordCommands-SXOCVBX7.js} +14 -14
  7. package/{agentRunCommand-R3RWG53B.js → agentRunCommand-XISX4ICI.js} +14 -14
  8. package/{agentRuntimeLocal-BD7R3OJL.js → agentRuntimeLocal-2ENB2B2Z.js} +5 -5
  9. package/{agentSlice-UP66DIC2.js → agentSlice-QLZWET7H.js} +1 -1
  10. package/{appDeleteCommands-X3UF4ZHF.js → appDeleteCommands-XKAUWKUI.js} +5 -5
  11. package/{appDeployCommands-MFHLJIYZ.js → appDeployCommands-SNXZY5IX.js} +5 -5
  12. package/{appDeployStatusCommands-BGXSUHY6.js → appDeployStatusCommands-NXUJ6LXS.js} +5 -5
  13. package/{appGetCommands-KEA6FZTF.js → appGetCommands-DNRYKGOK.js} +5 -5
  14. package/{appListCommands-CZGMZW3L.js → appListCommands-URESGUKU.js} +5 -5
  15. package/{chatQueueReduxAdapter-VVXE2NXW.js → chatQueueReduxAdapter-FNXZNIAT.js} +4 -4
  16. package/{chunk-HQ3ZLBSI.js → chunk-2XENHR3P.js} +96 -0
  17. package/{chunk-TDTSQVDX.js → chunk-3E67YXGD.js} +85 -88
  18. package/{chunk-RCNQCXPM.js → chunk-5JTJG4OG.js} +115 -121
  19. package/{chunk-MN2XJEWL.js → chunk-7NG5APVZ.js} +16 -133
  20. package/{chunk-UZXOOSHF.js → chunk-AUA5DTWI.js} +15 -14
  21. package/{chunk-HPRMNGAM.js → chunk-IX6H4NKR.js} +1 -1
  22. package/{chunk-UBWLW3KY.js → chunk-IY2BLZKO.js} +3 -3
  23. package/{chunk-5DUAG5G7.js → chunk-K4326DRU.js} +202 -11729
  24. package/{chunk-AVJQ4TDL.js → chunk-K5YS7FAN.js} +1 -1
  25. package/{chunk-TTTW4DIT.js → chunk-LNOW66U4.js} +6 -6
  26. package/{chunk-NFTTUZ3L.js → chunk-LTLZPAO7.js} +1 -1
  27. package/{chunk-QPXRNDI3.js → chunk-MIN5X7GI.js} +2 -2
  28. package/{chunk-OHJWIXXW.js → chunk-RLZ6HZSX.js} +3 -3
  29. package/{chunk-BG7ZGBKH.js → chunk-SM4ED2LZ.js} +4 -4
  30. package/{chunk-FPT2E44F.js → chunk-VHADFQCI.js} +2 -2
  31. package/{chunk-UNAVSDC5.js → chunk-XHNOCBUU.js} +4 -2
  32. package/chunk-XNO3T6RB.js +18504 -0
  33. package/chunk-Z6S2JBE4.js +2471 -0
  34. package/{chunk-M3HN7RBV.js → chunk-ZCVO2HLZ.js} +1 -1
  35. package/{contentThunks-BHML6O7K.js → contentThunks-6K4RZXKH.js} +5 -5
  36. package/{createAgentAutomationAction-K5YJO4IA.js → createAgentAutomationAction-6XYIZ3GS.js} +5 -5
  37. package/{createDialogAction-SFMZLPS4.js → createDialogAction-TJWDXAKL.js} +6 -6
  38. package/{createPageAction-UD7BSFQS.js → createPageAction-EZ2LPB6K.js} +5 -5
  39. package/{dialogCommands-2ABSL4ND.js → dialogCommands-ULXMRIAM.js} +5 -5
  40. package/{dialogSlice-DEC5GV6X.js → dialogSlice-5DRM6AQQ.js} +4 -4
  41. package/{docCreateCommands-2QZCW4HZ.js → docCreateCommands-PPHO6KUM.js} +5 -5
  42. package/{docDeleteCommands-WKZKQAKM.js → docDeleteCommands-U2GVGQPR.js} +5 -5
  43. package/{docReadCommands-WMKJCR4Q.js → docReadCommands-CYY3DJXY.js} +5 -5
  44. package/{docStore-IBPCRTTX.js → docStore-OJXM46BB.js} +1 -1
  45. package/{docUpdateCommands-KPLM63NK.js → docUpdateCommands-B5UVFLJU.js} +5 -5
  46. package/{handleSendMessageAction-C7CZNGMB.js → handleSendMessageAction-EWY3J2AV.js} +4 -4
  47. package/index.js +41 -41
  48. package/{machineCommands-6BG3AHT5.js → machineCommands-B76BYAJF.js} +14 -14
  49. package/{machineWsRunDispatch-G2KJ6NQF.js → machineWsRunDispatch-LN6274EL.js} +14 -14
  50. package/package.json +1 -1
  51. package/{readlineWorkspace-5LZ3EDIQ.js → readlineWorkspace-UFHEJIDS.js} +77 -18
  52. package/{runAgentClientLoop-CICP3O2T.js → runAgentClientLoop-MAER6Y5K.js} +11 -11
  53. package/{spaceCommands-NQOIERT6.js → spaceCommands-2YT7C56D.js} +5 -5
  54. package/{streamAgentChatTurn-QUD4FY5I.js → streamAgentChatTurn-AKUDQL5W.js} +14 -14
  55. package/{tools-MAP6O2YZ.js → tools-NM36O7ZG.js} +8 -8
  56. package/{tuiSummaryLlmCaller-VL5RDGLT.js → tuiSummaryLlmCaller-ZGATEM35.js} +2 -2
  57. package/{updateDialogTitleAction-L6CCRVUK.js → updateDialogTitleAction-RHH353JB.js} +5 -5
  58. package/chunk-CLZYOOI3.js +0 -4463
  59. package/chunk-IF6UQNAK.js +0 -5062
@@ -8,7 +8,7 @@ import {
8
8
  readSseFrames,
9
9
  streamSseDataValues,
10
10
  throwIfChatCompletionStreamFailed
11
- } from "./chunk-M3HN7RBV.js";
11
+ } from "./chunk-ZCVO2HLZ.js";
12
12
  import {
13
13
  clipToolText,
14
14
  hasImageInRuntimeMessages,
@@ -39,7 +39,7 @@ import {
39
39
  requiresBareImageUrl,
40
40
  resolveToolGuidedSections,
41
41
  toBareImageUrlMessages
42
- } from "./chunk-AVJQ4TDL.js";
42
+ } from "./chunk-K5YS7FAN.js";
43
43
  import {
44
44
  convertMessagesToResponsesInput,
45
45
  extractReasoningFromResponseOutput,
@@ -80,16 +80,16 @@ import {
80
80
  EMPTY_ASSISTANT_REPAIR_PROMPT,
81
81
  getModelContextWindow,
82
82
  hasAssistantVisibleOutput,
83
+ normalizeUsage,
83
84
  readCacheCreationInputTokens,
84
85
  readCacheReadInputTokens,
85
86
  resolveEmptyAssistantFallbackMessage,
86
87
  resolveEmptyAssistantOutcome,
87
88
  resolveTruncatedReasoningTailLog
88
- } from "./chunk-HQ3ZLBSI.js";
89
+ } from "./chunk-2XENHR3P.js";
89
90
  import {
90
91
  COMPACTION_SUMMARY_SCHEMA_VERSION,
91
92
  COMPACTION_SUMMARY_SYSTEM_PROMPT,
92
- TOOL_STUB_TEXT,
93
93
  buildCompactionMetricsFromPlan,
94
94
  buildCompactionUserContent,
95
95
  clipCompactText,
@@ -102,8 +102,10 @@ import {
102
102
  observeMeaningfulProviderResponse,
103
103
  planCompression,
104
104
  planContextUsage,
105
+ resolveCompressionTriggerRatio,
106
+ truncateToolOutputForContext,
105
107
  withProviderCallTimingFields
106
- } from "./chunk-TDTSQVDX.js";
108
+ } from "./chunk-3E67YXGD.js";
107
109
  import {
108
110
  estimateTokenCount
109
111
  } from "./chunk-PSCNXBYA.js";
@@ -12404,35 +12406,10 @@ function projectHistoryWithSummary(args2) {
12404
12406
  const found = bridged.findIndex((m) => m.id === args2.summarizedBeforeId);
12405
12407
  if (found !== -1) startIndex = found + 1;
12406
12408
  }
12407
- let stubEndIndex = -1;
12408
- if (args2.stubbedBeforeId) {
12409
- const found = bridged.findIndex((m) => m.id === args2.stubbedBeforeId);
12410
- if (found !== -1) stubEndIndex = found;
12411
- }
12412
- const projected = args2.history.slice(startIndex).map((message, i) => {
12413
- const absIndex = startIndex + i;
12414
- if (stubEndIndex !== -1 && message.role === "tool" && absIndex <= stubEndIndex) {
12415
- const content = typeof message.content === "string" ? TOOL_STUB_TEXT : Array.isArray(message.content) ? [{ type: "text", text: TOOL_STUB_TEXT }] : TOOL_STUB_TEXT;
12416
- return { ...message, content };
12417
- }
12418
- return message;
12419
- });
12409
+ const projected = args2.history.slice(startIndex);
12420
12410
  const summaryMsg = args2.summary.trim().length > 0 ? [buildLocalSummaryHistoryMessage(args2.summary)] : [];
12421
12411
  return [...summaryMsg, ...projected];
12422
12412
  }
12423
- function applyStoredStubToHistory(history, stubbedBeforeId) {
12424
- if (!stubbedBeforeId) return history;
12425
- const bridged = toPlanCompressionMessages(history);
12426
- const stubEndIndex = bridged.findIndex((m) => m.id === stubbedBeforeId);
12427
- if (stubEndIndex === -1) return history;
12428
- return history.map((message, i) => {
12429
- if (i <= stubEndIndex && message.role === "tool") {
12430
- const content = typeof message.content === "string" ? TOOL_STUB_TEXT : Array.isArray(message.content) ? [{ type: "text", text: TOOL_STUB_TEXT }] : TOOL_STUB_TEXT;
12431
- return { ...message, content };
12432
- }
12433
- return message;
12434
- });
12435
- }
12436
12413
  var COLD_RESUME_IDLE_MS = 60 * 60 * 1e3;
12437
12414
  function isColdResume(history, nowMs) {
12438
12415
  for (let i = history.length - 1; i >= 0; i -= 1) {
@@ -12482,31 +12459,24 @@ async function maybeAutoCompactLocalHistory(args2) {
12482
12459
  }
12483
12460
  const existingSummary = typeof stored?.summary === "string" ? stored.summary : "";
12484
12461
  const summarizedBeforeId = typeof stored?.summarizedBeforeId === "string" ? stored.summarizedBeforeId : void 0;
12485
- const storedStubbedBeforeId = typeof stored?.stubbedBeforeId === "string" && stored.stubbedBeforeId ? stored.stubbedBeforeId : void 0;
12486
12462
  const contextWindow = typeof args2.contextWindow === "number" && Number.isFinite(args2.contextWindow) && args2.contextWindow > 0 ? args2.contextWindow : getModelContextWindow(args2.model ?? "");
12487
- const allMsgs = toPlanCompressionMessages(
12488
- applyStoredStubToHistory(history, storedStubbedBeforeId)
12489
- );
12463
+ const allMsgs = toPlanCompressionMessages(history);
12490
12464
  const coldResume = isColdResume(history, args2.now?.() ?? Date.now());
12491
12465
  const plan = planCompression({
12492
12466
  allMsgs,
12493
12467
  summarizedBeforeId,
12494
12468
  summary: existingSummary,
12495
12469
  contextWindow,
12496
- // 防死亡螺旋:用 summary 长度作为上次压缩后的基线。如果新内容没让
12497
- // totalUsed 比 summary 本身增长超过 minNewTokens,不重复触发。
12498
- lastCompactedTokenCount: existingSummary ? estimateTokenCount(existingSummary) : void 0,
12499
- ...coldResume ? { force: true, reason: "context_budget" } : {},
12470
+ ...coldResume ? { coldResume: true, reason: "cold_resume" } : {},
12500
12471
  ...args2.realContextUsagePercent !== void 0 ? { realContextUsagePercent: args2.realContextUsagePercent } : {}
12501
12472
  });
12502
12473
  const projectExisting = () => {
12503
- if (!existingSummary.trim() && !storedStubbedBeforeId) return unchanged();
12474
+ if (!existingSummary.trim()) return unchanged();
12504
12475
  return {
12505
12476
  history: projectHistoryWithSummary({
12506
12477
  history,
12507
12478
  summary: existingSummary,
12508
- summarizedBeforeId,
12509
- stubbedBeforeId: storedStubbedBeforeId
12479
+ summarizedBeforeId
12510
12480
  }),
12511
12481
  compressed: true,
12512
12482
  summaryGenerated: false
@@ -12515,49 +12485,6 @@ async function maybeAutoCompactLocalHistory(args2) {
12515
12485
  if (!plan.shouldCompress) {
12516
12486
  return projectExisting();
12517
12487
  }
12518
- if (plan.stub) {
12519
- const nextStubbedBeforeId = plan.stub.beforeId;
12520
- const changed = nextStubbedBeforeId !== storedStubbedBeforeId;
12521
- if (changed) {
12522
- try {
12523
- await adapter.saveDialogSummary({
12524
- dialogId,
12525
- summary: existingSummary,
12526
- summarizedBeforeId,
12527
- stubbedBeforeId: nextStubbedBeforeId,
12528
- // stub 档不改锚点切片 → 透传源校验字段保持读写对称
12529
- sourceHash: stored?.sourceHash,
12530
- sourceCount: stored?.sourceCount,
12531
- schemaVersion: COMPACTION_SUMMARY_SCHEMA_VERSION
12532
- });
12533
- } catch (error) {
12534
- console.warn("[localLoop] saveDialogSummary (stub) failed:", error);
12535
- }
12536
- }
12537
- const metrics = buildCompactionMetricsFromPlan({
12538
- reason: "tool_stub",
12539
- previousSummary: existingSummary,
12540
- plan,
12541
- newSummary: existingSummary
12542
- });
12543
- console.log(formatCompactionMetricsLog(metrics));
12544
- return {
12545
- history: projectHistoryWithSummary({
12546
- history,
12547
- summary: existingSummary,
12548
- summarizedBeforeId,
12549
- stubbedBeforeId: nextStubbedBeforeId
12550
- }),
12551
- compressed: true,
12552
- summaryGenerated: false,
12553
- metrics,
12554
- reason: "tool_stub",
12555
- savedTokens: plan.stub.savedTokens,
12556
- stubbedCount: plan.stub.stubbedCount,
12557
- beforeTokens: metrics.previousSummaryTokens + metrics.compressedTokens,
12558
- afterTokens: metrics.newSummaryTokens + metrics.retainedTokens
12559
- };
12560
- }
12561
12488
  try {
12562
12489
  const provider = await args2.resolveProvider();
12563
12490
  const msgsToCompress = plan.msgsToCompress;
@@ -12580,14 +12507,15 @@ async function maybeAutoCompactLocalHistory(args2) {
12580
12507
  console.warn(
12581
12508
  "[localLoop] auto-compaction produced empty summary; keeping prior projection"
12582
12509
  );
12583
- return projectExisting();
12510
+ return {
12511
+ ...projectExisting(),
12512
+ failureMessage: "summary model returned empty content"
12513
+ };
12584
12514
  }
12585
12515
  await adapter.saveDialogSummary({
12586
12516
  dialogId,
12587
12517
  summary: newSummary,
12588
12518
  summarizedBeforeId: plan.newSummarizedBeforeId,
12589
- // 新摘要已覆盖 stub 区间 → 清空 stubbedBeforeId
12590
- stubbedBeforeId: void 0,
12591
12519
  // 内容寻址失效检测:存锚点切片哈希与长度,供下轮载入校验。
12592
12520
  sourceHash: hashSummarySourceSlice(history, plan.newSummarizedBeforeId),
12593
12521
  sourceCount: (() => {
@@ -12622,7 +12550,8 @@ async function maybeAutoCompactLocalHistory(args2) {
12622
12550
  };
12623
12551
  } catch (error) {
12624
12552
  console.warn("[localLoop] auto-compaction failed:", error);
12625
- return projectExisting();
12553
+ const failureMessage = error instanceof Error && error.message ? error.message.slice(0, 200) : String(error).slice(0, 200);
12554
+ return { ...projectExisting(), failureMessage };
12626
12555
  }
12627
12556
  }
12628
12557
 
@@ -13572,6 +13501,7 @@ async function runLocalAgentTurn(input) {
13572
13501
  throw error;
13573
13502
  }
13574
13503
  loopTimingMark("loadDialogHistory", 0);
13504
+ const canonicalHistory = history;
13575
13505
  const identityBlock = buildIdentityBlock({
13576
13506
  agentName: agentConfig.name,
13577
13507
  agentId: agentConfig.key,
@@ -13609,6 +13539,8 @@ async function runLocalAgentTurn(input) {
13609
13539
  }
13610
13540
  return resolvedProvider;
13611
13541
  };
13542
+ const contextWindow = getModelContextWindow(agentConfig.model ?? "");
13543
+ const compressionTriggerRatio = resolveCompressionTriggerRatio(contextWindow);
13612
13544
  let realContextUsagePercent;
13613
13545
  if (input.continueDialogId && typeof input.adapter.loadLastContextUsage === "function") {
13614
13546
  try {
@@ -13616,7 +13548,6 @@ async function runLocalAgentTurn(input) {
13616
13548
  input.continueDialogId
13617
13549
  );
13618
13550
  const inputTokens = usage?.inputTokens;
13619
- const contextWindow = getModelContextWindow(agentConfig.model);
13620
13551
  if (typeof inputTokens === "number" && Number.isFinite(inputTokens) && inputTokens > 0 && typeof contextWindow === "number" && Number.isFinite(contextWindow) && contextWindow > 0) {
13621
13552
  realContextUsagePercent = Math.min(
13622
13553
  1,
@@ -13628,6 +13559,21 @@ async function runLocalAgentTurn(input) {
13628
13559
  }
13629
13560
  }
13630
13561
  let compactionUsage;
13562
+ const emitCompactionObservation = (compacted) => {
13563
+ if (compacted.compressed || compacted.summaryGenerated || compacted.failureMessage) {
13564
+ emitLoopEvent(observationBoundary, {
13565
+ kind: "compaction",
13566
+ atMs: Date.now(),
13567
+ reason: compacted.reason ?? "context_budget",
13568
+ summaryGenerated: compacted.summaryGenerated,
13569
+ compressed: compacted.compressed,
13570
+ ...compacted.failureMessage ? { failed: true, detail: compacted.failureMessage } : {},
13571
+ ...compacted.beforeTokens !== void 0 ? { beforeTokens: compacted.beforeTokens } : {},
13572
+ ...compacted.afterTokens !== void 0 ? { afterTokens: compacted.afterTokens } : {},
13573
+ ...compacted.savedTokens !== void 0 ? { savedTokens: compacted.savedTokens } : {}
13574
+ });
13575
+ }
13576
+ };
13631
13577
  try {
13632
13578
  const compacted = await maybeAutoCompactLocalHistory({
13633
13579
  adapter: input.adapter,
@@ -13639,19 +13585,7 @@ async function runLocalAgentTurn(input) {
13639
13585
  });
13640
13586
  history = compacted.history;
13641
13587
  compactionUsage = compacted.usage;
13642
- if (compacted.compressed || compacted.summaryGenerated) {
13643
- emitLoopEvent(observationBoundary, {
13644
- kind: "compaction",
13645
- atMs: Date.now(),
13646
- reason: compacted.reason ?? "context_budget",
13647
- summaryGenerated: compacted.summaryGenerated,
13648
- compressed: compacted.compressed,
13649
- ...compacted.beforeTokens !== void 0 ? { beforeTokens: compacted.beforeTokens } : {},
13650
- ...compacted.afterTokens !== void 0 ? { afterTokens: compacted.afterTokens } : {},
13651
- ...compacted.savedTokens !== void 0 ? { savedTokens: compacted.savedTokens } : {},
13652
- ...compacted.stubbedCount !== void 0 ? { stubbedCount: compacted.stubbedCount } : {}
13653
- });
13654
- }
13588
+ emitCompactionObservation(compacted);
13655
13589
  } catch (error) {
13656
13590
  console.warn("[localLoop] auto-compaction unexpected error:", error);
13657
13591
  }
@@ -13663,7 +13597,6 @@ async function runLocalAgentTurn(input) {
13663
13597
  loopTimingMark("trimHistoryToContextBudget", 0);
13664
13598
  const hasContextBlocks = callerScopes.some((block) => block.content.trim()) || mergedContextBlockScopes.some((block) => block.content.trim());
13665
13599
  const promptMessageCount = agentConfig.prompt?.trim() || hasContextBlocks ? 1 : 0;
13666
- const turnStartIndex = promptMessageCount + history.length;
13667
13600
  const builtMessages = buildMessages({
13668
13601
  prompt: agentConfig.prompt,
13669
13602
  contextBlockScopes: mergedContextBlockScopes,
@@ -13694,6 +13627,17 @@ async function runLocalAgentTurn(input) {
13694
13627
  atMs: Date.now()
13695
13628
  });
13696
13629
  }
13630
+ const rawTurnMessages = messages.slice(
13631
+ promptMessageCount + history.length
13632
+ );
13633
+ const pushMessage = (msg) => {
13634
+ messages.push(msg);
13635
+ rawTurnMessages.push(msg);
13636
+ };
13637
+ const capToolMessage = (msg) => msg.role === "tool" && typeof msg.content === "string" ? {
13638
+ ...msg,
13639
+ content: truncateToolOutputForContext(msg.content, contextWindow)
13640
+ } : msg;
13697
13641
  const userInputText = extractUserInputText(input.input);
13698
13642
  let toolCallCount = 0;
13699
13643
  let result4;
@@ -13708,6 +13652,50 @@ async function runLocalAgentTurn(input) {
13708
13652
  let skipFinalAppend = false;
13709
13653
  let partialContent = "";
13710
13654
  const progressGuard = createLocalLoopProgressGuard(input.progressGuardConfig);
13655
+ const maybeCompactInLoop = async () => {
13656
+ if (!input.continueDialogId) return;
13657
+ if (!contextUsage) return;
13658
+ const inputTokens = normalizeUsage(contextUsage).input_tokens;
13659
+ if (!inputTokens || inputTokens <= 0) return;
13660
+ const ratio = Math.min(1, inputTokens / contextWindow);
13661
+ if (ratio < compressionTriggerRatio) return;
13662
+ try {
13663
+ const compacted = await maybeAutoCompactLocalHistory({
13664
+ adapter: input.adapter,
13665
+ dialogId: input.continueDialogId,
13666
+ // canonical 坐标:store 全量历史 + 本轮消息的「持久化形态」
13667
+ // (applyPersistedTurnInput 会把首条 user 消息换成 paste 展开形态)。
13668
+ // 锚点与 sourceHash 都必须按持久化形态计算——否则下轮从 store
13669
+ // 重载后重算 hash 必不匹配,摘要被判无效、白付一次摘要调用。
13670
+ history: [
13671
+ ...canonicalHistory,
13672
+ ...applyPersistedTurnInput(
13673
+ rawTurnMessages,
13674
+ input.persistedInput,
13675
+ input.persistedInputReference
13676
+ )
13677
+ ],
13678
+ model: agentConfig.model,
13679
+ resolveProvider: resolveProviderOnce,
13680
+ realContextUsagePercent: ratio
13681
+ });
13682
+ if (compacted.usage) {
13683
+ compactionUsage = addOutOfBandUsage(compactionUsage, compacted.usage);
13684
+ }
13685
+ if (compacted.compressed) {
13686
+ messages = downgradeUnparsableToolCalls([
13687
+ ...messages.slice(0, promptMessageCount),
13688
+ ...prepareHistoryForNextTurn(
13689
+ compacted.history,
13690
+ input.adapter.host === "cli" ? input.contextReferenceResolver : void 0
13691
+ )
13692
+ ]).messages;
13693
+ }
13694
+ emitCompactionObservation(compacted);
13695
+ } catch (error) {
13696
+ console.warn("[localLoop] in-loop auto-compaction failed:", error);
13697
+ }
13698
+ };
13711
13699
  try {
13712
13700
  const provider = await resolveProviderOnce();
13713
13701
  const applyPendingInjections = () => {
@@ -13722,7 +13710,7 @@ async function runLocalAgentTurn(input) {
13722
13710
  let injected = false;
13723
13711
  for (const text of pending) {
13724
13712
  if (typeof text !== "string" || !text.trim()) continue;
13725
- messages.push({ role: "user", content: text });
13713
+ pushMessage({ role: "user", content: text });
13726
13714
  injected = true;
13727
13715
  }
13728
13716
  return injected;
@@ -13904,13 +13892,14 @@ ${reasoningTailLog}
13904
13892
  content: result4.content,
13905
13893
  ...result4.reasoning_content ? { reasoning_content: result4.reasoning_content } : {}
13906
13894
  };
13907
- messages.push(assistantMessage);
13895
+ pushMessage(assistantMessage);
13908
13896
  if (applyPendingInjections()) {
13909
13897
  loopTimingMark("roundEnd", round);
13910
13898
  round += 1;
13911
13899
  continue;
13912
13900
  }
13913
13901
  messages.pop();
13902
+ rawTurnMessages.pop();
13914
13903
  }
13915
13904
  break;
13916
13905
  }
@@ -13930,7 +13919,9 @@ ${reasoningTailLog}
13930
13919
  }
13931
13920
  }
13932
13921
  if (hasInlineExecutedTools) {
13933
- messages.push(...blocksToOpenAiMessages(outputBlocks));
13922
+ for (const blockMsg of blocksToOpenAiMessages(outputBlocks)) {
13923
+ pushMessage(capToolMessage(blockMsg));
13924
+ }
13934
13925
  skipFinalAppend = true;
13935
13926
  break;
13936
13927
  }
@@ -13938,7 +13929,7 @@ ${reasoningTailLog}
13938
13929
  continue;
13939
13930
  }
13940
13931
  toolCallCount += toolCalls.length;
13941
- messages.push({
13932
+ pushMessage({
13942
13933
  role: "assistant",
13943
13934
  content: result4.content || null,
13944
13935
  ...result4.reasoning_content ? { reasoning_content: result4.reasoning_content } : {},
@@ -14114,17 +14105,19 @@ ${reasoningTailLog}
14114
14105
  metadata: toolResult.metadata
14115
14106
  });
14116
14107
  loopTimingMark("toolResultFormat", round);
14117
- messages.push({
14118
- role: "tool",
14119
- content: formatToolMessageContent({
14108
+ pushMessage(
14109
+ capToolMessage({
14110
+ role: "tool",
14111
+ content: formatToolMessageContent({
14112
+ toolName,
14113
+ content: toolResult.content,
14114
+ metadata: observedMetadata
14115
+ }),
14116
+ tool_call_id: toolCall.id,
14120
14117
  toolName,
14121
- content: toolResult.content,
14122
- metadata: observedMetadata
14123
- }),
14124
- tool_call_id: toolCall.id,
14125
- toolName,
14126
- ...observedMetadata ? { tool_result_metadata: observedMetadata } : {}
14127
- });
14118
+ ...observedMetadata ? { tool_result_metadata: observedMetadata } : {}
14119
+ })
14120
+ );
14128
14121
  }
14129
14122
  const toolExecutionGuardVerdict = progressGuard.observeToolExecution(
14130
14123
  toolCalls,
@@ -14146,6 +14139,7 @@ ${reasoningTailLog}
14146
14139
  };
14147
14140
  break;
14148
14141
  }
14142
+ await maybeCompactInLoop();
14149
14143
  loopTimingMark("roundEnd", round);
14150
14144
  round += 1;
14151
14145
  }
@@ -14154,7 +14148,7 @@ ${reasoningTailLog}
14154
14148
  }
14155
14149
  if (loopError) {
14156
14150
  const turnMessages2 = applyPersistedTurnInput(
14157
- messages.slice(turnStartIndex),
14151
+ rawTurnMessages,
14158
14152
  input.persistedInput,
14159
14153
  input.persistedInputReference
14160
14154
  );
@@ -14192,7 +14186,7 @@ ${reasoningTailLog}
14192
14186
  result4.emptyAssistantFallbackReason,
14193
14187
  result4.reasoning_content
14194
14188
  );
14195
- messages.push({
14189
+ pushMessage({
14196
14190
  role: "assistant",
14197
14191
  content: result4.content,
14198
14192
  // 与中间轮(:561)一致带上 reasoning_content,让 saveTurn 持久化思维链,
@@ -14202,7 +14196,7 @@ ${reasoningTailLog}
14202
14196
  });
14203
14197
  }
14204
14198
  const turnMessages = applyPersistedTurnInput(
14205
- messages.slice(turnStartIndex),
14199
+ rawTurnMessages,
14206
14200
  input.persistedInput,
14207
14201
  input.persistedInputReference
14208
14202
  );