@librechat/agents 3.7.8 → 3.7.10

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/dist/cjs/agents/AgentContext.cjs +3 -2
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/constants.cjs +2 -0
  4. package/dist/cjs/common/constants.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +40 -6
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  8. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  9. package/dist/cjs/hooks/executeHooks.cjs +8 -0
  10. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  11. package/dist/cjs/hooks/index.cjs +2 -0
  12. package/dist/cjs/hooks/index.cjs.map +1 -1
  13. package/dist/cjs/hooks/types.cjs +1 -0
  14. package/dist/cjs/hooks/types.cjs.map +1 -1
  15. package/dist/cjs/langfuse.cjs +43 -3
  16. package/dist/cjs/langfuse.cjs.map +1 -1
  17. package/dist/cjs/llm/invoke.cjs +2 -6
  18. package/dist/cjs/llm/invoke.cjs.map +1 -1
  19. package/dist/cjs/llm/request.cjs +6 -0
  20. package/dist/cjs/llm/request.cjs.map +1 -1
  21. package/dist/cjs/main.cjs +19 -11
  22. package/dist/cjs/messages/format.cjs +95 -18
  23. package/dist/cjs/messages/format.cjs.map +1 -1
  24. package/dist/cjs/messages/index.cjs +1 -1
  25. package/dist/cjs/run.cjs +201 -46
  26. package/dist/cjs/run.cjs.map +1 -1
  27. package/dist/cjs/session/AgentSession.cjs +1 -1
  28. package/dist/cjs/session/JsonlSessionStore.cjs +1 -1
  29. package/dist/cjs/summarization/index.cjs +1 -0
  30. package/dist/cjs/summarization/index.cjs.map +1 -1
  31. package/dist/cjs/summarization/node.cjs +24 -85
  32. package/dist/cjs/summarization/node.cjs.map +1 -1
  33. package/dist/cjs/summarization/semanticIndex.cjs +7 -3
  34. package/dist/cjs/summarization/semanticIndex.cjs.map +1 -1
  35. package/dist/cjs/summarization/shared.cjs +83 -0
  36. package/dist/cjs/summarization/shared.cjs.map +1 -0
  37. package/dist/cjs/tools/ToolNode.cjs +5 -5
  38. package/dist/cjs/tools/local/CompileCheckTool.cjs +1 -1
  39. package/dist/cjs/tools/local/LocalCodingTools.cjs +1 -1
  40. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +1 -1
  41. package/dist/cjs/tools/runStepResume.cjs +1 -1
  42. package/dist/cjs/tools/runStepResume.cjs.map +1 -1
  43. package/dist/cjs/tools/search/metrics.cjs +234 -0
  44. package/dist/cjs/tools/search/metrics.cjs.map +1 -0
  45. package/dist/cjs/tools/search/rerankers.cjs +80 -68
  46. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  47. package/dist/cjs/tools/search/search.cjs +95 -45
  48. package/dist/cjs/tools/search/search.cjs.map +1 -1
  49. package/dist/cjs/tools/search/tool.cjs +77 -49
  50. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  51. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  52. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +8 -12
  53. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  54. package/dist/cjs/utils/tokens.cjs +8 -1
  55. package/dist/cjs/utils/tokens.cjs.map +1 -1
  56. package/dist/esm/agents/AgentContext.mjs +3 -2
  57. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  58. package/dist/esm/common/constants.mjs +2 -1
  59. package/dist/esm/common/constants.mjs.map +1 -1
  60. package/dist/esm/graphs/Graph.mjs +40 -6
  61. package/dist/esm/graphs/Graph.mjs.map +1 -1
  62. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  63. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  64. package/dist/esm/hooks/executeHooks.mjs +8 -1
  65. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  66. package/dist/esm/hooks/index.mjs +2 -1
  67. package/dist/esm/hooks/index.mjs.map +1 -1
  68. package/dist/esm/hooks/types.mjs +1 -0
  69. package/dist/esm/hooks/types.mjs.map +1 -1
  70. package/dist/esm/langfuse.mjs +43 -3
  71. package/dist/esm/langfuse.mjs.map +1 -1
  72. package/dist/esm/llm/invoke.mjs +2 -6
  73. package/dist/esm/llm/invoke.mjs.map +1 -1
  74. package/dist/esm/llm/request.mjs +6 -1
  75. package/dist/esm/llm/request.mjs.map +1 -1
  76. package/dist/esm/main.mjs +13 -12
  77. package/dist/esm/messages/format.mjs +96 -19
  78. package/dist/esm/messages/format.mjs.map +1 -1
  79. package/dist/esm/messages/index.mjs +1 -1
  80. package/dist/esm/run.mjs +201 -46
  81. package/dist/esm/run.mjs.map +1 -1
  82. package/dist/esm/session/AgentSession.mjs +1 -1
  83. package/dist/esm/session/JsonlSessionStore.mjs +1 -1
  84. package/dist/esm/summarization/index.mjs +1 -0
  85. package/dist/esm/summarization/index.mjs.map +1 -1
  86. package/dist/esm/summarization/node.mjs +21 -82
  87. package/dist/esm/summarization/node.mjs.map +1 -1
  88. package/dist/esm/summarization/semanticIndex.mjs +7 -4
  89. package/dist/esm/summarization/semanticIndex.mjs.map +1 -1
  90. package/dist/esm/summarization/shared.mjs +79 -0
  91. package/dist/esm/summarization/shared.mjs.map +1 -0
  92. package/dist/esm/tools/ToolNode.mjs +5 -5
  93. package/dist/esm/tools/local/CompileCheckTool.mjs +1 -1
  94. package/dist/esm/tools/local/LocalCodingTools.mjs +1 -1
  95. package/dist/esm/tools/local/LocalExecutionEngine.mjs +1 -1
  96. package/dist/esm/tools/runStepResume.mjs +1 -1
  97. package/dist/esm/tools/runStepResume.mjs.map +1 -1
  98. package/dist/esm/tools/search/metrics.mjs +234 -0
  99. package/dist/esm/tools/search/metrics.mjs.map +1 -0
  100. package/dist/esm/tools/search/rerankers.mjs +80 -68
  101. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  102. package/dist/esm/tools/search/search.mjs +96 -46
  103. package/dist/esm/tools/search/search.mjs.map +1 -1
  104. package/dist/esm/tools/search/tool.mjs +77 -49
  105. package/dist/esm/tools/search/tool.mjs.map +1 -1
  106. package/dist/esm/tools/search/utils.mjs.map +1 -1
  107. package/dist/esm/tools/subagent/SubagentExecutor.mjs +8 -12
  108. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  109. package/dist/esm/utils/tokens.mjs +8 -2
  110. package/dist/esm/utils/tokens.mjs.map +1 -1
  111. package/dist/types/common/constants.d.ts +7 -0
  112. package/dist/types/graphs/Graph.d.ts +9 -0
  113. package/dist/types/hooks/executeHooks.d.ts +5 -2
  114. package/dist/types/hooks/index.d.ts +7 -2
  115. package/dist/types/hooks/types.d.ts +45 -7
  116. package/dist/types/langfuse.d.ts +3 -1
  117. package/dist/types/llm/request.d.ts +10 -0
  118. package/dist/types/messages/format.d.ts +8 -2
  119. package/dist/types/run.d.ts +2 -1
  120. package/dist/types/summarization/index.d.ts +6 -0
  121. package/dist/types/summarization/node.d.ts +0 -4
  122. package/dist/types/summarization/semanticIndex.d.ts +2 -0
  123. package/dist/types/summarization/shared.d.ts +25 -0
  124. package/dist/types/tools/search/metrics.d.ts +15 -0
  125. package/dist/types/tools/search/rerankers.d.ts +30 -5
  126. package/dist/types/tools/search/tool.d.ts +7 -1
  127. package/dist/types/tools/search/types.d.ts +88 -4
  128. package/dist/types/tools/search/utils.d.ts +2 -10
  129. package/dist/types/types/run.d.ts +8 -0
  130. package/dist/types/types/stream.d.ts +6 -0
  131. package/dist/types/types/summarize.d.ts +6 -0
  132. package/dist/types/utils/tokens.d.ts +9 -0
  133. package/package.json +1 -1
  134. package/src/agents/AgentContext.ts +2 -5
  135. package/src/common/constants.ts +8 -0
  136. package/src/graphs/Graph.ts +45 -0
  137. package/src/hooks/HookRegistry.ts +3 -1
  138. package/src/hooks/executeHooks.ts +20 -2
  139. package/src/hooks/index.ts +12 -1
  140. package/src/hooks/types.ts +47 -4
  141. package/src/langfuse.ts +70 -0
  142. package/src/llm/invoke.ts +13 -29
  143. package/src/llm/request.ts +24 -0
  144. package/src/messages/format.ts +213 -27
  145. package/src/run.ts +366 -186
  146. package/src/summarization/index.ts +11 -0
  147. package/src/summarization/node.ts +117 -130
  148. package/src/summarization/semanticIndex.ts +16 -7
  149. package/src/summarization/shared.ts +130 -0
  150. package/src/tools/runStepResume.ts +9 -0
  151. package/src/tools/search/metrics.ts +400 -0
  152. package/src/tools/search/rerankers.ts +160 -97
  153. package/src/tools/search/search.ts +139 -56
  154. package/src/tools/search/tool.ts +126 -62
  155. package/src/tools/search/types.ts +104 -4
  156. package/src/tools/search/utils.ts +2 -10
  157. package/src/tools/subagent/SubagentExecutor.ts +4 -27
  158. package/src/types/run.ts +8 -0
  159. package/src/types/stream.ts +6 -0
  160. package/src/types/summarize.ts +7 -0
  161. package/src/utils/tokens.ts +31 -8
@@ -30,6 +30,7 @@ import type {
30
30
  ProviderName,
31
31
  CompactionSemanticIndex,
32
32
  CompactionSemanticIndexEntry,
33
+ CompactionSemanticIndexSnapshot,
33
34
  } from '@/types';
34
35
  import type {
35
36
  ProviderMessageAttribution,
@@ -52,23 +53,27 @@ import {
52
53
  setInvalidProviderMessageProvenance,
53
54
  setProviderMessageProvenance,
54
55
  } from './provenance';
56
+ import {
57
+ snapshotCompactionSemanticIndex,
58
+ getCompactionSemanticIndexProvidedEntryCount,
59
+ setCompactionSemanticIndexProvidedEntryCount,
60
+ } from '@/summarization/semanticIndex';
55
61
  import {
56
62
  compactToolContent,
57
63
  getToolContentCharLength,
58
64
  isAtomicToolContentBlock,
59
65
  serializeStructuredValueBounded,
60
66
  } from '@/utils/toolContent';
61
- import { setCompactionSemanticIndexProvidedEntryCount } from '@/summarization/semanticIndex';
62
- import { normalizeAnthropicToolCallId } from '@/llm/anthropic/utils/message_inputs';
63
- import { toLangChainContent, toLangChainMessageFields } from './langchain';
64
- import { flattenLegacyContent, isLegacyConvertible } from './content';
65
- import { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';
66
67
  import {
67
68
  Providers,
68
69
  ContentTypes,
69
70
  Constants,
70
71
  COMPACTION_SEMANTIC_INDEX_LIMITS,
71
72
  } from '@/common';
73
+ import { normalizeAnthropicToolCallId } from '@/llm/anthropic/utils/message_inputs';
74
+ import { toLangChainContent, toLangChainMessageFields } from './langchain';
75
+ import { flattenLegacyContent, isLegacyConvertible } from './content';
76
+ import { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';
72
77
  import { emitAgentLog } from '@/utils/events';
73
78
 
74
79
  interface MediaMessageParams {
@@ -389,7 +394,7 @@ interface FormatAssistantMessageOptions {
389
394
 
390
395
  type SourceContentPartIndices = number | readonly number[];
391
396
 
392
- interface FormatAgentMessagesOptions {
397
+ export interface FormatAgentMessagesOptions {
393
398
  provider?: ProviderName;
394
399
  /** Emit flattenable text content as the joined string the legacy-content
395
400
  * projection would produce, so the per-request `formatContentStrings` pass
@@ -410,6 +415,10 @@ interface FormatAgentMessagesOptions {
410
415
  * the host identifies as semantic-label fields; business `intent`
411
416
  * parameters must remain ordinary tool input. */
412
417
  compactionSemanticIndex?: {
418
+ /** Previously committed, serializable guidance to evolve with entries
419
+ * derived from this payload. The formatter snapshots and validates
420
+ * caller-owned data before scanning the new messages. */
421
+ baseSnapshot?: CompactionSemanticIndexSnapshot;
413
422
  intentToolNames?: ReadonlySet<string>;
414
423
  };
415
424
  }
@@ -533,9 +542,17 @@ type CompactionSemanticCoverageState = {
533
542
  >;
534
543
  };
535
544
 
545
+ type CompactionSemanticRevisionFloor = {
546
+ entry: CompactionSemanticIndexEntry;
547
+ order: number;
548
+ };
549
+
536
550
  type DerivedCompactionSemanticIndexCollector = {
537
551
  entries: CompactionSemanticIndexEntry[];
538
552
  entryCount: number;
553
+ baseEntryCount: number;
554
+ omittedBaseEntryCount: number;
555
+ baseRevisionFloors?: Map<number, CompactionSemanticRevisionFloor[]>;
539
556
  coverage?: CompactionSemanticCoverageState;
540
557
  };
541
558
 
@@ -554,11 +571,47 @@ const DERIVED_SEMANTIC_TYPE_HASH: Readonly<
554
571
  reasoning_label: 4,
555
572
  });
556
573
 
557
- function createDerivedCompactionSemanticIndexCollector(): DerivedCompactionSemanticIndexCollector {
558
- return {
574
+ function createDerivedCompactionSemanticIndexCollector(
575
+ baseSnapshot?: CompactionSemanticIndexSnapshot
576
+ ): DerivedCompactionSemanticIndexCollector {
577
+ const collector: DerivedCompactionSemanticIndexCollector = {
559
578
  entries: [],
560
579
  entryCount: 0,
580
+ baseEntryCount: 0,
581
+ omittedBaseEntryCount: 0,
561
582
  };
583
+ let baseEntries: CompactionSemanticIndex | undefined;
584
+ let serializedProvidedEntryCount: number | undefined;
585
+ try {
586
+ baseEntries = baseSnapshot?.entries;
587
+ serializedProvidedEntryCount = baseSnapshot?.providedEntryCount;
588
+ } catch {
589
+ return collector;
590
+ }
591
+ const snapshot = snapshotCompactionSemanticIndex(baseEntries);
592
+ if (snapshot == null) {
593
+ return collector;
594
+ }
595
+ const snapshotProvidedEntryCount =
596
+ getCompactionSemanticIndexProvidedEntryCount(snapshot);
597
+ const validSerializedProvidedEntryCount =
598
+ typeof serializedProvidedEntryCount === 'number' &&
599
+ Number.isSafeInteger(serializedProvidedEntryCount) &&
600
+ serializedProvidedEntryCount >= snapshotProvidedEntryCount;
601
+ const providedEntryCount =
602
+ validSerializedProvidedEntryCount &&
603
+ serializedProvidedEntryCount != null
604
+ ? serializedProvidedEntryCount
605
+ : snapshotProvidedEntryCount;
606
+ collector.omittedBaseEntryCount = Math.max(
607
+ 0,
608
+ providedEntryCount - snapshot.length
609
+ );
610
+ for (let index = 0; index < snapshot.length; index++) {
611
+ appendDerivedCompactionSemanticEntry(collector, snapshot[index], true);
612
+ }
613
+ collector.baseEntryCount = collector.entryCount;
614
+ return collector;
562
615
  }
563
616
 
564
617
  function createCompactionSemanticCoverageState(): CompactionSemanticCoverageState {
@@ -637,6 +690,86 @@ function entriesHaveConflictingSemanticState(
637
690
  );
638
691
  }
639
692
 
693
+ function findCompactionSemanticRevisionFloor(
694
+ collector: DerivedCompactionSemanticIndexCollector,
695
+ entry: CompactionSemanticIndexEntry,
696
+ identityHash: number
697
+ ): CompactionSemanticRevisionFloor | undefined {
698
+ return collector.baseRevisionFloors
699
+ ?.get(identityHash)
700
+ ?.find((floor) =>
701
+ entriesShareDerivedCompactionSemanticIdentity(floor.entry, entry)
702
+ );
703
+ }
704
+
705
+ function seedCompactionSemanticRevisionFloor(
706
+ collector: DerivedCompactionSemanticIndexCollector,
707
+ entry: CompactionSemanticIndexEntry,
708
+ order: number
709
+ ): void {
710
+ collector.baseRevisionFloors ??= new Map();
711
+ const identityHash = hashDerivedCompactionSemanticIdentity(entry);
712
+ const existing = findCompactionSemanticRevisionFloor(
713
+ collector,
714
+ entry,
715
+ identityHash
716
+ );
717
+ if (existing != null) {
718
+ if (entry.revision > existing.entry.revision) {
719
+ existing.entry = entry;
720
+ existing.order = order;
721
+ }
722
+ return;
723
+ }
724
+ const floor = { entry, order };
725
+ const bucket = collector.baseRevisionFloors.get(identityHash);
726
+ if (bucket == null) {
727
+ collector.baseRevisionFloors.set(identityHash, [floor]);
728
+ return;
729
+ }
730
+ bucket.push(floor);
731
+ }
732
+
733
+ function updateCompactionSemanticRevisionFloor(
734
+ collector: DerivedCompactionSemanticIndexCollector,
735
+ orderedEntry: OrderedCompactionSemanticIndexEntry
736
+ ): void {
737
+ const floor = findCompactionSemanticRevisionFloor(
738
+ collector,
739
+ orderedEntry.entry,
740
+ orderedEntry.identityHash
741
+ );
742
+ if (floor == null || orderedEntry.entry.revision <= floor.entry.revision) {
743
+ return;
744
+ }
745
+ floor.entry = orderedEntry.entry;
746
+ floor.order = orderedEntry.order;
747
+ }
748
+
749
+ function shouldRejectCompactionSemanticEntryBelowBaseFloor(
750
+ collector: DerivedCompactionSemanticIndexCollector,
751
+ orderedEntry: OrderedCompactionSemanticIndexEntry
752
+ ): boolean {
753
+ const floor = findCompactionSemanticRevisionFloor(
754
+ collector,
755
+ orderedEntry.entry,
756
+ orderedEntry.identityHash
757
+ );
758
+ if (floor == null || orderedEntry.order === floor.order) {
759
+ return false;
760
+ }
761
+ const currentBucket = collector.coverage?.latestByIdentityHash.get(
762
+ orderedEntry.identityHash
763
+ );
764
+ const current = currentBucket?.find(({ entry }) =>
765
+ entriesShareDerivedCompactionSemanticIdentity(entry, orderedEntry.entry)
766
+ );
767
+ if (current != null) {
768
+ return false;
769
+ }
770
+ return orderedEntry.entry.revision <= floor.entry.revision;
771
+ }
772
+
640
773
  function retainCompactionSemanticEntry(
641
774
  entry: OrderedCompactionSemanticIndexEntry
642
775
  ): void {
@@ -738,7 +871,8 @@ function renewCoverageBalancedCompactionSemanticEntry(
738
871
 
739
872
  function appendDerivedCompactionSemanticEntry(
740
873
  collector: DerivedCompactionSemanticIndexCollector,
741
- entry: CompactionSemanticIndexEntry
874
+ entry: CompactionSemanticIndexEntry,
875
+ baseEntry = false
742
876
  ): void {
743
877
  let boundedEntry = entry;
744
878
  if (entry.status === 'pending') {
@@ -755,6 +889,14 @@ function appendDerivedCompactionSemanticEntry(
755
889
  collector.entries.length < COMPACTION_SEMANTIC_INDEX_LIMITS.maxInputEntries
756
890
  ) {
757
891
  collector.entries.push(boundedEntry);
892
+ if (!baseEntry && collector.baseRevisionFloors != null) {
893
+ updateCompactionSemanticRevisionFloor(collector, {
894
+ entry: boundedEntry,
895
+ identityHash: hashDerivedCompactionSemanticIdentity(boundedEntry),
896
+ order,
897
+ retentionCount: 0,
898
+ });
899
+ }
758
900
  return;
759
901
  }
760
902
  const orderedEntry = {
@@ -764,23 +906,54 @@ function appendDerivedCompactionSemanticEntry(
764
906
  retentionCount: 0,
765
907
  };
766
908
  if (collector.coverage == null) {
909
+ for (let order = 0; order < collector.baseEntryCount; order++) {
910
+ seedCompactionSemanticRevisionFloor(
911
+ collector,
912
+ collector.entries[order],
913
+ order
914
+ );
915
+ }
767
916
  collector.coverage = createCompactionSemanticCoverageState();
768
917
  for (let order = 0; order < collector.entries.length; order++) {
769
- appendCoverageBalancedCompactionSemanticEntry(collector.coverage, {
918
+ const bufferedEntry = {
770
919
  entry: collector.entries[order],
771
920
  identityHash: hashDerivedCompactionSemanticIdentity(
772
921
  collector.entries[order]
773
922
  ),
774
923
  order,
775
924
  retentionCount: 0,
776
- });
925
+ };
926
+ if (
927
+ shouldRejectCompactionSemanticEntryBelowBaseFloor(
928
+ collector,
929
+ bufferedEntry
930
+ )
931
+ ) {
932
+ continue;
933
+ }
934
+ appendCoverageBalancedCompactionSemanticEntry(
935
+ collector.coverage,
936
+ bufferedEntry
937
+ );
938
+ if (order >= collector.baseEntryCount) {
939
+ updateCompactionSemanticRevisionFloor(collector, bufferedEntry);
940
+ }
777
941
  }
778
942
  collector.entries = [];
779
943
  }
944
+ if (
945
+ !baseEntry &&
946
+ shouldRejectCompactionSemanticEntryBelowBaseFloor(collector, orderedEntry)
947
+ ) {
948
+ return;
949
+ }
780
950
  appendCoverageBalancedCompactionSemanticEntry(
781
951
  collector.coverage,
782
952
  orderedEntry
783
953
  );
954
+ if (!baseEntry) {
955
+ updateCompactionSemanticRevisionFloor(collector, orderedEntry);
956
+ }
784
957
  }
785
958
 
786
959
  function appendCoverageBalancedCompactionSemanticEntry(
@@ -843,18 +1016,25 @@ function appendCoverageBalancedCompactionSemanticEntry(
843
1016
  );
844
1017
  }
845
1018
 
846
- function finalizeDerivedCompactionSemanticIndex(
1019
+ function finalizeDerivedCompactionSemanticIndexSnapshot(
847
1020
  collector: DerivedCompactionSemanticIndexCollector | undefined
848
- ): CompactionSemanticIndex | undefined {
849
- if (collector == null || collector.entryCount === 0) {
1021
+ ): CompactionSemanticIndexSnapshot | undefined {
1022
+ if (
1023
+ collector == null ||
1024
+ (collector.entryCount === 0 && collector.omittedBaseEntryCount === 0)
1025
+ ) {
850
1026
  return undefined;
851
1027
  }
1028
+ const providedEntryCount = Math.min(
1029
+ Number.MAX_SAFE_INTEGER,
1030
+ collector.entryCount + collector.omittedBaseEntryCount
1031
+ );
852
1032
  if (collector.coverage == null) {
853
1033
  setCompactionSemanticIndexProvidedEntryCount(
854
1034
  collector.entries,
855
- collector.entryCount
1035
+ providedEntryCount
856
1036
  );
857
- return collector.entries;
1037
+ return { entries: collector.entries, providedEntryCount };
858
1038
  }
859
1039
  const retained = new Map<number, CompactionSemanticIndexEntry>();
860
1040
  const retain = (
@@ -873,8 +1053,8 @@ function finalizeDerivedCompactionSemanticIndex(
873
1053
  const result = [...retained.entries()]
874
1054
  .sort(([left], [right]) => left - right)
875
1055
  .map(([, entry]) => entry);
876
- setCompactionSemanticIndexProvidedEntryCount(result, collector.entryCount);
877
- return result;
1056
+ setCompactionSemanticIndexProvidedEntryCount(result, providedEntryCount);
1057
+ return { entries: result, providedEntryCount };
878
1058
  }
879
1059
 
880
1060
  function collectCompactionSemanticEntriesFromPart(
@@ -888,8 +1068,7 @@ function collectCompactionSemanticEntriesFromPart(
888
1068
  parsedToolInput?: ToolCallPart['args']
889
1069
  ): void {
890
1070
  if (
891
- sourceMessageId.length >
892
- COMPACTION_SEMANTIC_INDEX_LIMITS.maxIdentityChars
1071
+ sourceMessageId.length > COMPACTION_SEMANTIC_INDEX_LIMITS.maxIdentityChars
893
1072
  ) {
894
1073
  return;
895
1074
  }
@@ -1017,14 +1196,14 @@ function collectCompactionSemanticEntriesFromPart(
1017
1196
  part.pending !== undefined && typeof part.pending !== 'boolean';
1018
1197
  const malformedText = typeof part.activity_label !== 'string';
1019
1198
  const malformedState = malformedPending || malformedText;
1020
- const text = typeof part.activity_label === 'string' ? part.activity_label : '';
1199
+ const text =
1200
+ typeof part.activity_label === 'string' ? part.activity_label : '';
1021
1201
  appendDerivedCompactionSemanticEntry(collector, {
1022
1202
  type: 'activity_phase',
1023
1203
  sourceMessageId,
1024
1204
  sourceContentIndex: activitySourceContentIndex,
1025
1205
  revision: revision ?? 0,
1026
- status:
1027
- part.pending === true || malformedPending ? 'pending' : 'committed',
1206
+ status: part.pending === true || malformedPending ? 'pending' : 'committed',
1028
1207
  text,
1029
1208
  ...(malformedState ? { redacted: true } : {}),
1030
1209
  });
@@ -2627,6 +2806,8 @@ export const formatAgentMessages = (
2627
2806
  boundaryTokenAdjustment?: SummaryTokenAdjustment;
2628
2807
  /** Bounded semantic guidance derived during persisted-content analysis. */
2629
2808
  compactionSemanticIndex?: CompactionSemanticIndex;
2809
+ /** Serializable continuation state for incrementally evolving the index. */
2810
+ compactionSemanticIndexSnapshot?: CompactionSemanticIndexSnapshot;
2630
2811
  } => {
2631
2812
  const messages: Array<
2632
2813
  | RoleBearingMessage<HumanMessage>
@@ -2643,7 +2824,9 @@ export const formatAgentMessages = (
2643
2824
  const legacyContentEnabled = options?.legacyContent === true;
2644
2825
  const compactionSemanticIndexCollector =
2645
2826
  options?.compactionSemanticIndex != null
2646
- ? createDerivedCompactionSemanticIndexCollector()
2827
+ ? createDerivedCompactionSemanticIndexCollector(
2828
+ options.compactionSemanticIndex.baseSnapshot
2829
+ )
2647
2830
  : undefined;
2648
2831
  /** Emission choke point: every formatted message enters the result here, so
2649
2832
  * the legacy flatten happens once per message with no closing rescan. The
@@ -3246,6 +3429,10 @@ export const formatAgentMessages = (
3246
3429
  }
3247
3430
  }
3248
3431
 
3432
+ const compactionSemanticIndexSnapshot =
3433
+ finalizeDerivedCompactionSemanticIndexSnapshot(
3434
+ compactionSemanticIndexCollector
3435
+ );
3249
3436
  return {
3250
3437
  messages,
3251
3438
  indexTokenCountMap: indexTokenCountMap
@@ -3255,9 +3442,8 @@ export const formatAgentMessages = (
3255
3442
  ? { text: summaryBoundary.text, tokenCount: summaryBoundary.tokenCount }
3256
3443
  : undefined,
3257
3444
  boundaryTokenAdjustment,
3258
- compactionSemanticIndex: finalizeDerivedCompactionSemanticIndex(
3259
- compactionSemanticIndexCollector
3260
- ),
3445
+ compactionSemanticIndex: compactionSemanticIndexSnapshot?.entries,
3446
+ compactionSemanticIndexSnapshot,
3261
3447
  };
3262
3448
  };
3263
3449