@librechat/agents 3.7.8 → 3.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/agents/AgentContext.cjs +3 -2
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/constants.cjs +2 -0
- package/dist/cjs/common/constants.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +40 -6
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/executeHooks.cjs +8 -0
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/hooks/index.cjs +2 -0
- package/dist/cjs/hooks/index.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +1 -0
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +43 -3
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +2 -6
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/request.cjs +6 -0
- package/dist/cjs/llm/request.cjs.map +1 -1
- package/dist/cjs/main.cjs +19 -11
- package/dist/cjs/messages/format.cjs +95 -18
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/index.cjs +1 -1
- package/dist/cjs/run.cjs +201 -46
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +1 -1
- package/dist/cjs/session/JsonlSessionStore.cjs +1 -1
- package/dist/cjs/summarization/index.cjs +1 -0
- package/dist/cjs/summarization/index.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +24 -85
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/summarization/semanticIndex.cjs +7 -3
- package/dist/cjs/summarization/semanticIndex.cjs.map +1 -1
- package/dist/cjs/summarization/shared.cjs +83 -0
- package/dist/cjs/summarization/shared.cjs.map +1 -0
- package/dist/cjs/tools/ToolNode.cjs +5 -5
- package/dist/cjs/tools/local/CompileCheckTool.cjs +1 -1
- package/dist/cjs/tools/local/LocalCodingTools.cjs +1 -1
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +1 -1
- package/dist/cjs/tools/runStepResume.cjs +1 -1
- package/dist/cjs/tools/runStepResume.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +8 -12
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +8 -1
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +3 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/constants.mjs +2 -1
- package/dist/esm/common/constants.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +40 -6
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/executeHooks.mjs +8 -1
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/hooks/index.mjs +2 -1
- package/dist/esm/hooks/index.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +1 -0
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +43 -3
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +2 -6
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/request.mjs +6 -1
- package/dist/esm/llm/request.mjs.map +1 -1
- package/dist/esm/main.mjs +13 -12
- package/dist/esm/messages/format.mjs +96 -19
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/index.mjs +1 -1
- package/dist/esm/run.mjs +201 -46
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +1 -1
- package/dist/esm/session/JsonlSessionStore.mjs +1 -1
- package/dist/esm/summarization/index.mjs +1 -0
- package/dist/esm/summarization/index.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +21 -82
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/summarization/semanticIndex.mjs +7 -4
- package/dist/esm/summarization/semanticIndex.mjs.map +1 -1
- package/dist/esm/summarization/shared.mjs +79 -0
- package/dist/esm/summarization/shared.mjs.map +1 -0
- package/dist/esm/tools/ToolNode.mjs +5 -5
- package/dist/esm/tools/local/CompileCheckTool.mjs +1 -1
- package/dist/esm/tools/local/LocalCodingTools.mjs +1 -1
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +1 -1
- package/dist/esm/tools/runStepResume.mjs +1 -1
- package/dist/esm/tools/runStepResume.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +8 -12
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +8 -2
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/common/constants.d.ts +7 -0
- package/dist/types/graphs/Graph.d.ts +9 -0
- package/dist/types/hooks/executeHooks.d.ts +5 -2
- package/dist/types/hooks/index.d.ts +7 -2
- package/dist/types/hooks/types.d.ts +45 -7
- package/dist/types/langfuse.d.ts +3 -1
- package/dist/types/llm/request.d.ts +10 -0
- package/dist/types/messages/format.d.ts +8 -2
- package/dist/types/run.d.ts +2 -1
- package/dist/types/summarization/index.d.ts +6 -0
- package/dist/types/summarization/node.d.ts +0 -4
- package/dist/types/summarization/semanticIndex.d.ts +2 -0
- package/dist/types/summarization/shared.d.ts +25 -0
- package/dist/types/types/run.d.ts +8 -0
- package/dist/types/types/stream.d.ts +6 -0
- package/dist/types/types/summarize.d.ts +6 -0
- package/dist/types/utils/tokens.d.ts +9 -0
- package/package.json +1 -1
- package/src/agents/AgentContext.ts +2 -5
- package/src/common/constants.ts +8 -0
- package/src/graphs/Graph.ts +45 -0
- package/src/hooks/HookRegistry.ts +3 -1
- package/src/hooks/executeHooks.ts +20 -2
- package/src/hooks/index.ts +12 -1
- package/src/hooks/types.ts +47 -4
- package/src/langfuse.ts +70 -0
- package/src/llm/invoke.ts +13 -29
- package/src/llm/request.ts +24 -0
- package/src/messages/format.ts +213 -27
- package/src/run.ts +366 -186
- package/src/summarization/index.ts +11 -0
- package/src/summarization/node.ts +117 -130
- package/src/summarization/semanticIndex.ts +16 -7
- package/src/summarization/shared.ts +130 -0
- package/src/tools/runStepResume.ts +9 -0
- package/src/tools/subagent/SubagentExecutor.ts +4 -27
- package/src/types/run.ts +8 -0
- package/src/types/stream.ts +6 -0
- package/src/types/summarize.ts +7 -0
- package/src/utils/tokens.ts +31 -8
package/src/llm/invoke.ts
CHANGED
|
@@ -27,6 +27,12 @@ import {
|
|
|
27
27
|
STREAM_LIMIT_REDISPATCH_KEY,
|
|
28
28
|
STREAM_LIMIT_ATTEMPT_KEY,
|
|
29
29
|
} from '@/llm/streamLimits';
|
|
30
|
+
import {
|
|
31
|
+
inspectProviderMessageProjection,
|
|
32
|
+
ProviderMessageProjectionInvariantError,
|
|
33
|
+
resolveProviderMessageProjectionInvariantMode,
|
|
34
|
+
modifyDeltaProperties,
|
|
35
|
+
} from '@/messages';
|
|
30
36
|
import {
|
|
31
37
|
assertPreparedProviderRequestFor,
|
|
32
38
|
prepareProviderRequest,
|
|
@@ -38,15 +44,10 @@ import {
|
|
|
38
44
|
import { ChatModelStreamHandler, dispatchesChatModelStream } from '@/stream';
|
|
39
45
|
import { Constants, ContentTypes, GraphEvents, Providers } from '@/common';
|
|
40
46
|
import { assertNotTruncatedToolCall } from '@/llm/truncation';
|
|
47
|
+
import { resolveClientOptionsModel } from '@/llm/request';
|
|
41
48
|
import { safeDispatchCustomEvent } from '@/utils/events';
|
|
42
49
|
import { getContextOverflowInfo } from '@/utils/errors';
|
|
43
50
|
import { appendCallbacks } from '@/utils/callbacks';
|
|
44
|
-
import {
|
|
45
|
-
inspectProviderMessageProjection,
|
|
46
|
-
ProviderMessageProjectionInvariantError,
|
|
47
|
-
resolveProviderMessageProjectionInvariantMode,
|
|
48
|
-
modifyDeltaProperties,
|
|
49
|
-
} from '@/messages';
|
|
50
51
|
import { canSealPreempt } from '@/llm/preempt';
|
|
51
52
|
import { initializeModel } from '@/llm/init';
|
|
52
53
|
|
|
@@ -715,8 +716,7 @@ async function attemptInvokeBody(
|
|
|
715
716
|
resolveProviderMessageProjectionInvariantMode();
|
|
716
717
|
let sealedRunId: string | undefined;
|
|
717
718
|
let invocationConfig = config;
|
|
718
|
-
const captureModelRunId =
|
|
719
|
-
model.stream != null && context?.preemption != null;
|
|
719
|
+
const captureModelRunId = model.stream != null && context?.preemption != null;
|
|
720
720
|
if (projectionInvariantMode !== 'off' || captureModelRunId) {
|
|
721
721
|
invocationConfig = withModelStartHandler({
|
|
722
722
|
config,
|
|
@@ -934,7 +934,10 @@ async function attemptInvokeBody(
|
|
|
934
934
|
return { messages: [finalChunk as AIMessageChunk] };
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
-
const finalMessage = await model.invoke(
|
|
937
|
+
const finalMessage = await model.invoke(
|
|
938
|
+
messagesForProvider,
|
|
939
|
+
invocationConfig
|
|
940
|
+
);
|
|
938
941
|
if ((finalMessage.tool_calls?.length ?? 0) > 0) {
|
|
939
942
|
finalMessage.tool_calls = finalMessage.tool_calls?.filter(
|
|
940
943
|
(tool_call: ToolCall) => !!tool_call.name
|
|
@@ -997,25 +1000,6 @@ export function getFallbackOverflowCandidates(
|
|
|
997
1000
|
return [...(fallbackOverflowCandidates.get(error) ?? [])];
|
|
998
1001
|
}
|
|
999
1002
|
|
|
1000
|
-
/**
|
|
1001
|
-
* Best-effort read of the configured model name from client options.
|
|
1002
|
-
* Providers disagree on the key (`model` vs `modelName`).
|
|
1003
|
-
*/
|
|
1004
|
-
function extractClientOptionsModel(
|
|
1005
|
-
clientOptions: t.ClientOptions | undefined
|
|
1006
|
-
): string | undefined {
|
|
1007
|
-
const options = clientOptions as
|
|
1008
|
-
| { model?: unknown; modelName?: unknown }
|
|
1009
|
-
| undefined;
|
|
1010
|
-
if (typeof options?.model === 'string' && options.model !== '') {
|
|
1011
|
-
return options.model;
|
|
1012
|
-
}
|
|
1013
|
-
if (typeof options?.modelName === 'string' && options.modelName !== '') {
|
|
1014
|
-
return options.modelName;
|
|
1015
|
-
}
|
|
1016
|
-
return undefined;
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
1003
|
/**
|
|
1020
1004
|
* Attempts each fallback provider in order until one succeeds.
|
|
1021
1005
|
*
|
|
@@ -1106,7 +1090,7 @@ export async function tryFallbackProviders({
|
|
|
1106
1090
|
* `ls_model_name`. The serving provider is stamped uniformly by
|
|
1107
1091
|
* `attemptInvoke` (`INVOKED_PROVIDER`).
|
|
1108
1092
|
*/
|
|
1109
|
-
const fbModelName =
|
|
1093
|
+
const fbModelName = resolveClientOptionsModel(fb.clientOptions);
|
|
1110
1094
|
const fbConfig: RunnableConfig | undefined =
|
|
1111
1095
|
fbModelName == null
|
|
1112
1096
|
? config
|
package/src/llm/request.ts
CHANGED
|
@@ -43,6 +43,30 @@ export function isThinkingEnabled(
|
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Model configured on client options, under whichever of the two keys carries
|
|
48
|
+
* it. LangChain accepts `modelName` as an alias for `model` and this package
|
|
49
|
+
* writes both (see `buildSummarizationClientConfig`), while hosts configure
|
|
50
|
+
* agents through either. Reading only one key therefore does not fail loudly:
|
|
51
|
+
* it reports an unconfigured model, and every caller here treats that as a cue
|
|
52
|
+
* to fall back to a default, so a Claude agent configured through the alias is
|
|
53
|
+
* silently handled as something else.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveClientOptionsModel(
|
|
56
|
+
clientOptions: t.ClientOptions | undefined
|
|
57
|
+
): string | undefined {
|
|
58
|
+
const options = clientOptions as
|
|
59
|
+
| { model?: unknown; modelName?: unknown }
|
|
60
|
+
| undefined;
|
|
61
|
+
if (typeof options?.model === 'string' && options.model !== '') {
|
|
62
|
+
return options.model;
|
|
63
|
+
}
|
|
64
|
+
if (typeof options?.modelName === 'string' && options.modelName !== '') {
|
|
65
|
+
return options.modelName;
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
/**
|
|
47
71
|
* Returns the correct key for setting max output tokens on the model
|
|
48
72
|
* constructor options. Google/Vertex use `maxOutputTokens`, all others
|
package/src/messages/format.ts
CHANGED
|
@@ -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(
|
|
558
|
-
|
|
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
|
-
|
|
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
|
|
1019
|
+
function finalizeDerivedCompactionSemanticIndexSnapshot(
|
|
847
1020
|
collector: DerivedCompactionSemanticIndexCollector | undefined
|
|
848
|
-
):
|
|
849
|
-
if (
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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:
|
|
3259
|
-
|
|
3260
|
-
),
|
|
3445
|
+
compactionSemanticIndex: compactionSemanticIndexSnapshot?.entries,
|
|
3446
|
+
compactionSemanticIndexSnapshot,
|
|
3261
3447
|
};
|
|
3262
3448
|
};
|
|
3263
3449
|
|