agentfootprint 7.16.0 → 7.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/conventions.js +8 -6
- package/dist/conventions.js.map +1 -1
- package/dist/core/Agent.js +31 -26
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +93 -43
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js +8 -8
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +6 -6
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/stages/window.js +141 -0
- package/dist/core/agent/stages/window.js.map +1 -0
- package/dist/core/agent/window/errors.js.map +1 -0
- package/dist/core/agent/window/index.js +36 -0
- package/dist/core/agent/window/index.js.map +1 -0
- package/dist/core/agent/window/notice.js +57 -0
- package/dist/core/agent/window/notice.js.map +1 -0
- package/dist/core/agent/window/options.js +93 -0
- package/dist/core/agent/window/options.js.map +1 -0
- package/dist/core/agent/window/removal.js +45 -0
- package/dist/core/agent/window/removal.js.map +1 -0
- package/dist/core/agent/window/strategies/drop.js +106 -0
- package/dist/core/agent/window/strategies/drop.js.map +1 -0
- package/dist/core/agent/window/strategies/slidingWindow.js +87 -0
- package/dist/core/agent/window/strategies/slidingWindow.js.map +1 -0
- package/dist/core/agent/window/strategies/summarizeOldest.js +178 -0
- package/dist/core/agent/window/strategies/summarizeOldest.js.map +1 -0
- package/dist/core/agent/window/strategies/tokenBudget.js +95 -0
- package/dist/core/agent/window/strategies/tokenBudget.js.map +1 -0
- package/dist/core/agent/window/strategy.js +42 -0
- package/dist/core/agent/window/strategy.js.map +1 -0
- package/dist/core/agent/window/summarize.js.map +1 -0
- package/dist/core/agent/{compaction → window}/turns.js +50 -28
- package/dist/core/agent/window/turns.js.map +1 -0
- package/dist/core/agent/window/types.js +23 -0
- package/dist/core/agent/window/types.js.map +1 -0
- package/dist/esm/conventions.d.ts +8 -6
- package/dist/esm/conventions.js +8 -6
- package/dist/esm/conventions.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +6 -6
- package/dist/esm/core/Agent.js +31 -26
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +60 -4
- package/dist/esm/core/agent/AgentBuilder.js +93 -43
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/buildAgentChart.d.ts +14 -7
- package/dist/esm/core/agent/buildAgentChart.js +8 -8
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +6 -6
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/stages/window.d.ts +63 -0
- package/dist/esm/core/agent/stages/window.js +137 -0
- package/dist/esm/core/agent/stages/window.js.map +1 -0
- package/dist/esm/core/agent/types.d.ts +15 -8
- package/dist/esm/core/agent/window/errors.js.map +1 -0
- package/dist/esm/core/agent/window/index.d.ts +27 -0
- package/dist/esm/core/agent/window/index.js +25 -0
- package/dist/esm/core/agent/window/index.js.map +1 -0
- package/dist/esm/core/agent/window/notice.d.ts +46 -0
- package/dist/esm/core/agent/window/notice.js +52 -0
- package/dist/esm/core/agent/window/notice.js.map +1 -0
- package/dist/esm/core/agent/window/options.d.ts +33 -0
- package/dist/esm/core/agent/window/options.js +87 -0
- package/dist/esm/core/agent/window/options.js.map +1 -0
- package/dist/esm/core/agent/window/removal.d.ts +22 -0
- package/dist/esm/core/agent/window/removal.js +40 -0
- package/dist/esm/core/agent/window/removal.js.map +1 -0
- package/dist/esm/core/agent/window/strategies/drop.d.ts +54 -0
- package/dist/esm/core/agent/window/strategies/drop.js +102 -0
- package/dist/esm/core/agent/window/strategies/drop.js.map +1 -0
- package/dist/esm/core/agent/window/strategies/slidingWindow.d.ts +48 -0
- package/dist/esm/core/agent/window/strategies/slidingWindow.js +83 -0
- package/dist/esm/core/agent/window/strategies/slidingWindow.js.map +1 -0
- package/dist/esm/core/agent/window/strategies/summarizeOldest.d.ts +42 -0
- package/dist/esm/core/agent/window/strategies/summarizeOldest.js +174 -0
- package/dist/esm/core/agent/window/strategies/summarizeOldest.js.map +1 -0
- package/dist/esm/core/agent/window/strategies/tokenBudget.d.ts +47 -0
- package/dist/esm/core/agent/window/strategies/tokenBudget.js +91 -0
- package/dist/esm/core/agent/window/strategies/tokenBudget.js.map +1 -0
- package/dist/esm/core/agent/window/strategy.d.ts +181 -0
- package/dist/esm/core/agent/window/strategy.js +41 -0
- package/dist/esm/core/agent/window/strategy.js.map +1 -0
- package/dist/esm/core/agent/window/summarize.js.map +1 -0
- package/dist/esm/core/agent/window/turns.d.ts +108 -0
- package/dist/esm/core/agent/{compaction → window}/turns.js +48 -26
- package/dist/esm/core/agent/window/turns.js.map +1 -0
- package/dist/esm/core/agent/window/types.d.ts +263 -0
- package/dist/esm/core/agent/window/types.js +22 -0
- package/dist/esm/core/agent/window/types.js.map +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +10 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/recorders/core/CompactionMeter.d.ts +25 -19
- package/dist/esm/recorders/core/CompactionMeter.js +27 -19
- package/dist/esm/recorders/core/CompactionMeter.js.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/recorders/core/CompactionMeter.js +27 -19
- package/dist/recorders/core/CompactionMeter.js.map +1 -1
- package/dist/types/conventions.d.ts +8 -6
- package/dist/types/conventions.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +6 -6
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +60 -4
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +14 -7
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/stages/window.d.ts +64 -0
- package/dist/types/core/agent/stages/window.d.ts.map +1 -0
- package/dist/types/core/agent/types.d.ts +15 -8
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/agent/window/errors.d.ts.map +1 -0
- package/dist/types/core/agent/window/index.d.ts +28 -0
- package/dist/types/core/agent/window/index.d.ts.map +1 -0
- package/dist/types/core/agent/window/notice.d.ts +47 -0
- package/dist/types/core/agent/window/notice.d.ts.map +1 -0
- package/dist/types/core/agent/window/options.d.ts +34 -0
- package/dist/types/core/agent/window/options.d.ts.map +1 -0
- package/dist/types/core/agent/window/removal.d.ts +23 -0
- package/dist/types/core/agent/window/removal.d.ts.map +1 -0
- package/dist/types/core/agent/window/strategies/drop.d.ts +55 -0
- package/dist/types/core/agent/window/strategies/drop.d.ts.map +1 -0
- package/dist/types/core/agent/window/strategies/slidingWindow.d.ts +49 -0
- package/dist/types/core/agent/window/strategies/slidingWindow.d.ts.map +1 -0
- package/dist/types/core/agent/window/strategies/summarizeOldest.d.ts +43 -0
- package/dist/types/core/agent/window/strategies/summarizeOldest.d.ts.map +1 -0
- package/dist/types/core/agent/window/strategies/tokenBudget.d.ts +48 -0
- package/dist/types/core/agent/window/strategies/tokenBudget.d.ts.map +1 -0
- package/dist/types/core/agent/window/strategy.d.ts +182 -0
- package/dist/types/core/agent/window/strategy.d.ts.map +1 -0
- package/dist/types/core/agent/window/summarize.d.ts.map +1 -0
- package/dist/types/core/agent/window/turns.d.ts +109 -0
- package/dist/types/core/agent/window/turns.d.ts.map +1 -0
- package/dist/types/core/agent/window/types.d.ts +264 -0
- package/dist/types/core/agent/window/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/recorders/core/CompactionMeter.d.ts +25 -19
- package/dist/types/recorders/core/CompactionMeter.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/core/agent/compaction/errors.js.map +0 -1
- package/dist/core/agent/compaction/index.js +0 -24
- package/dist/core/agent/compaction/index.js.map +0 -1
- package/dist/core/agent/compaction/strategy.js +0 -152
- package/dist/core/agent/compaction/strategy.js.map +0 -1
- package/dist/core/agent/compaction/summarize.js.map +0 -1
- package/dist/core/agent/compaction/turns.js.map +0 -1
- package/dist/core/agent/compaction/types.js +0 -21
- package/dist/core/agent/compaction/types.js.map +0 -1
- package/dist/core/agent/stages/compact.js +0 -130
- package/dist/core/agent/stages/compact.js.map +0 -1
- package/dist/esm/core/agent/compaction/errors.js.map +0 -1
- package/dist/esm/core/agent/compaction/index.d.ts +0 -18
- package/dist/esm/core/agent/compaction/index.js +0 -18
- package/dist/esm/core/agent/compaction/index.js.map +0 -1
- package/dist/esm/core/agent/compaction/strategy.d.ts +0 -103
- package/dist/esm/core/agent/compaction/strategy.js +0 -148
- package/dist/esm/core/agent/compaction/strategy.js.map +0 -1
- package/dist/esm/core/agent/compaction/summarize.js.map +0 -1
- package/dist/esm/core/agent/compaction/turns.d.ts +0 -85
- package/dist/esm/core/agent/compaction/turns.js.map +0 -1
- package/dist/esm/core/agent/compaction/types.d.ts +0 -148
- package/dist/esm/core/agent/compaction/types.js +0 -20
- package/dist/esm/core/agent/compaction/types.js.map +0 -1
- package/dist/esm/core/agent/stages/compact.d.ts +0 -59
- package/dist/esm/core/agent/stages/compact.js +0 -126
- package/dist/esm/core/agent/stages/compact.js.map +0 -1
- package/dist/types/core/agent/compaction/errors.d.ts.map +0 -1
- package/dist/types/core/agent/compaction/index.d.ts +0 -19
- package/dist/types/core/agent/compaction/index.d.ts.map +0 -1
- package/dist/types/core/agent/compaction/strategy.d.ts +0 -104
- package/dist/types/core/agent/compaction/strategy.d.ts.map +0 -1
- package/dist/types/core/agent/compaction/summarize.d.ts.map +0 -1
- package/dist/types/core/agent/compaction/turns.d.ts +0 -86
- package/dist/types/core/agent/compaction/turns.d.ts.map +0 -1
- package/dist/types/core/agent/compaction/types.d.ts +0 -149
- package/dist/types/core/agent/compaction/types.d.ts.map +0 -1
- package/dist/types/core/agent/stages/compact.d.ts +0 -60
- package/dist/types/core/agent/stages/compact.d.ts.map +0 -1
- /package/dist/core/agent/{compaction → window}/errors.js +0 -0
- /package/dist/core/agent/{compaction → window}/summarize.js +0 -0
- /package/dist/esm/core/agent/{compaction → window}/errors.d.ts +0 -0
- /package/dist/esm/core/agent/{compaction → window}/errors.js +0 -0
- /package/dist/esm/core/agent/{compaction → window}/summarize.d.ts +0 -0
- /package/dist/esm/core/agent/{compaction → window}/summarize.js +0 -0
- /package/dist/types/core/agent/{compaction → window}/errors.d.ts +0 -0
- /package/dist/types/core/agent/{compaction → window}/summarize.d.ts +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* window/turns — where a turn boundary is, and which turns may leave.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Pure functions over the window (no scope, no I/O, no clock).
|
|
5
|
+
* Role: core/ layer. THE refusal engine. Every window strategy — the three
|
|
6
|
+
* that ship, and any a consumer writes — decides what leaves the
|
|
7
|
+
* window by calling these functions and nothing else, because the
|
|
8
|
+
* whole safety argument of the family lives here:
|
|
9
|
+
*
|
|
10
|
+
* a removal that splits an assistant's `tool_use` from its
|
|
11
|
+
* `tool_result` produces a request the vendor rejects, and a
|
|
12
|
+
* removal that swallows an unanswered question destroys the
|
|
13
|
+
* referent of the answer that has not arrived yet.
|
|
14
|
+
*
|
|
15
|
+
* Strategies never import this module. `WindowStrategyInput` hands
|
|
16
|
+
* them `planRemoval` already bound to this iteration's turns and
|
|
17
|
+
* guards, so a strategy CANNOT skip the refusal rules — that is a
|
|
18
|
+
* property of the seam, not of the documentation.
|
|
19
|
+
* Emits: N/A.
|
|
20
|
+
*
|
|
21
|
+
* Testable on its own — see `test/core/window-turns.test.ts`.
|
|
22
|
+
*/
|
|
23
|
+
import type { LLMMessage } from '../../../adapters/types.js';
|
|
24
|
+
import type { WindowRefusal, WindowRefusalReason } from './types.js';
|
|
25
|
+
/**
|
|
26
|
+
* One turn: a `user` / `assistant` / `system` message plus every `tool`
|
|
27
|
+
* message that answers it. Tool results belong to the assistant turn that
|
|
28
|
+
* requested them — that pairing is the thing a removal must never break.
|
|
29
|
+
*/
|
|
30
|
+
export interface Turn {
|
|
31
|
+
/** Index of this turn in the segmentation. */
|
|
32
|
+
readonly index: number;
|
|
33
|
+
/** Index of the turn's FIRST message in the window. */
|
|
34
|
+
readonly start: number;
|
|
35
|
+
/** Number of messages in the turn. */
|
|
36
|
+
readonly length: number;
|
|
37
|
+
readonly messages: readonly LLMMessage[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Segment a window into turns.
|
|
41
|
+
*
|
|
42
|
+
* A new turn starts at any non-`tool` message; `tool` messages join the turn
|
|
43
|
+
* in progress. A leading `tool` message (only reachable from a hand-built
|
|
44
|
+
* history) starts its own turn rather than being silently dropped.
|
|
45
|
+
*/
|
|
46
|
+
export declare function segmentTurns(history: readonly LLMMessage[]): readonly Turn[];
|
|
47
|
+
/**
|
|
48
|
+
* Context a removal decision needs beyond the turn itself.
|
|
49
|
+
*
|
|
50
|
+
* Internal: the stage builds it from scope and binds it into the
|
|
51
|
+
* `planRemoval` a strategy is handed, so no strategy has to know it exists.
|
|
52
|
+
*/
|
|
53
|
+
export interface RemovalGuards {
|
|
54
|
+
/** Every `toolCallId` answered anywhere in the window. */
|
|
55
|
+
readonly answeredCallIds: ReadonlySet<string>;
|
|
56
|
+
/** The tool call this run is paused on, when it is paused. */
|
|
57
|
+
readonly pausedToolCallId?: string;
|
|
58
|
+
/** True when the pause is a check-in (human consent) rather than askHuman. */
|
|
59
|
+
readonly pausedCheckIn?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/** Every tool_call id that has a matching `role: 'tool'` message. */
|
|
62
|
+
export declare function answeredCallIds(history: readonly LLMMessage[]): ReadonlySet<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Why this turn may NOT leave the window, or `undefined` when it may.
|
|
65
|
+
*
|
|
66
|
+
* Order matters only for which reason gets reported first; every check is
|
|
67
|
+
* independent. `paused-tool` / `pending-check-in` are separated from
|
|
68
|
+
* `unresolved-tool-call` on purpose: they are the same shape but a different
|
|
69
|
+
* fact about the world, and "we are waiting on a human" is what the person
|
|
70
|
+
* reading the trace needs to see.
|
|
71
|
+
*/
|
|
72
|
+
export declare function refusalFor(turn: Turn, guards: RemovalGuards): WindowRefusalReason | undefined;
|
|
73
|
+
/** The span a removal will take, plus every refusal it had to name to get there. */
|
|
74
|
+
export interface RemovalPlan {
|
|
75
|
+
/** First turn index in the span; -1 when nothing may be removed. */
|
|
76
|
+
readonly from: number;
|
|
77
|
+
/** Last turn index in the span (inclusive); -1 when nothing may be removed. */
|
|
78
|
+
readonly to: number;
|
|
79
|
+
readonly refusals: readonly WindowRefusal[];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Choose the removal span: the LONGEST CONTIGUOUS run of removable candidate
|
|
83
|
+
* turns, starting at the oldest removable one.
|
|
84
|
+
*
|
|
85
|
+
* Contiguity is not fussiness — it is what keeps the conversation in order.
|
|
86
|
+
* A fold replaces its span with ONE summary message; if the span skipped over
|
|
87
|
+
* an unremovable turn, that turn would end up after a summary of things that
|
|
88
|
+
* happened before it. So an unremovable turn at the front is stepped over (the
|
|
89
|
+
* span "takes the next oldest instead") and an unremovable turn in the middle
|
|
90
|
+
* ends the span. Everything not removed keeps its position.
|
|
91
|
+
*
|
|
92
|
+
* The drop strategies take the same span for a second reason: it is what makes
|
|
93
|
+
* a refusal reason mean the same thing under every strategy. A turn that ends
|
|
94
|
+
* the span this iteration is retried the next one — by which time the tool
|
|
95
|
+
* result it was waiting on has usually arrived.
|
|
96
|
+
*
|
|
97
|
+
* @param turns the window's turn segmentation
|
|
98
|
+
* @param keepRecent how many trailing turns are off-limits
|
|
99
|
+
* @param guards what must not leave (unanswered calls, the pause)
|
|
100
|
+
* @param isExistingSummary optional: true for a turn that is a summary a prior
|
|
101
|
+
* fold wrote. When the whole span is one such turn, the plan refuses with
|
|
102
|
+
* `only-existing-summary` — re-summarizing a summary spends an LLM call to
|
|
103
|
+
* lose detail. The drop strategies omit it: a drop spends nothing, so there
|
|
104
|
+
* is nothing to protect against.
|
|
105
|
+
*/
|
|
106
|
+
export declare function planRemoval(turns: readonly Turn[], keepRecent: number, guards: RemovalGuards, isExistingSummary?: (turn: Turn) => boolean): RemovalPlan;
|
|
107
|
+
/** Total characters of message content in a window. Exact; not tokens. */
|
|
108
|
+
export declare function windowChars(history: readonly LLMMessage[]): number;
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* window/turns — where a turn boundary is, and which turns may leave.
|
|
3
3
|
*
|
|
4
4
|
* Pattern: Pure functions over the window (no scope, no I/O, no clock).
|
|
5
|
-
* Role: core/ layer.
|
|
6
|
-
* a
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Role: core/ layer. THE refusal engine. Every window strategy — the three
|
|
6
|
+
* that ship, and any a consumer writes — decides what leaves the
|
|
7
|
+
* window by calling these functions and nothing else, because the
|
|
8
|
+
* whole safety argument of the family lives here:
|
|
9
|
+
*
|
|
10
|
+
* a removal that splits an assistant's `tool_use` from its
|
|
11
|
+
* `tool_result` produces a request the vendor rejects, and a
|
|
12
|
+
* removal that swallows an unanswered question destroys the
|
|
13
|
+
* referent of the answer that has not arrived yet.
|
|
14
|
+
*
|
|
15
|
+
* Strategies never import this module. `WindowStrategyInput` hands
|
|
16
|
+
* them `planRemoval` already bound to this iteration's turns and
|
|
17
|
+
* guards, so a strategy CANNOT skip the refusal rules — that is a
|
|
18
|
+
* property of the seam, not of the documentation.
|
|
10
19
|
* Emits: N/A.
|
|
11
20
|
*
|
|
12
|
-
* Testable on its own — see `test/core/
|
|
21
|
+
* Testable on its own — see `test/core/window-turns.test.ts`.
|
|
13
22
|
*/
|
|
14
23
|
/**
|
|
15
24
|
* Segment a window into turns.
|
|
@@ -49,7 +58,7 @@ export function answeredCallIds(history) {
|
|
|
49
58
|
return answered;
|
|
50
59
|
}
|
|
51
60
|
/**
|
|
52
|
-
* Why this turn may NOT
|
|
61
|
+
* Why this turn may NOT leave the window, or `undefined` when it may.
|
|
53
62
|
*
|
|
54
63
|
* Order matters only for which reason gets reported first; every check is
|
|
55
64
|
* independent. `paused-tool` / `pending-check-in` are separated from
|
|
@@ -57,44 +66,53 @@ export function answeredCallIds(history) {
|
|
|
57
66
|
* fact about the world, and "we are waiting on a human" is what the person
|
|
58
67
|
* reading the trace needs to see.
|
|
59
68
|
*/
|
|
60
|
-
export function refusalFor(turn,
|
|
69
|
+
export function refusalFor(turn, guards) {
|
|
61
70
|
for (const msg of turn.messages) {
|
|
62
71
|
if (msg.role === 'system')
|
|
63
72
|
return 'system-envelope';
|
|
64
73
|
}
|
|
65
|
-
const paused =
|
|
74
|
+
const paused = guards.pausedToolCallId;
|
|
66
75
|
if (paused !== undefined && paused.length > 0) {
|
|
67
76
|
for (const msg of turn.messages) {
|
|
68
77
|
const holdsPaused = msg.toolCallId === paused || (msg.toolCalls ?? []).some((tc) => tc.id === paused);
|
|
69
78
|
if (holdsPaused)
|
|
70
|
-
return
|
|
79
|
+
return guards.pausedCheckIn === true ? 'pending-check-in' : 'paused-tool';
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
82
|
for (const msg of turn.messages) {
|
|
74
83
|
for (const call of msg.toolCalls ?? []) {
|
|
75
|
-
if (!
|
|
84
|
+
if (!guards.answeredCallIds.has(call.id))
|
|
76
85
|
return 'unresolved-tool-call';
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
88
|
return undefined;
|
|
80
89
|
}
|
|
81
90
|
/**
|
|
82
|
-
* Choose the
|
|
83
|
-
* turns, starting at the oldest
|
|
91
|
+
* Choose the removal span: the LONGEST CONTIGUOUS run of removable candidate
|
|
92
|
+
* turns, starting at the oldest removable one.
|
|
84
93
|
*
|
|
85
94
|
* Contiguity is not fussiness — it is what keeps the conversation in order.
|
|
86
95
|
* A fold replaces its span with ONE summary message; if the span skipped over
|
|
87
|
-
* an
|
|
88
|
-
* happened before it. So an
|
|
89
|
-
*
|
|
90
|
-
* ends the span. Everything not
|
|
96
|
+
* an unremovable turn, that turn would end up after a summary of things that
|
|
97
|
+
* happened before it. So an unremovable turn at the front is stepped over (the
|
|
98
|
+
* span "takes the next oldest instead") and an unremovable turn in the middle
|
|
99
|
+
* ends the span. Everything not removed keeps its position.
|
|
100
|
+
*
|
|
101
|
+
* The drop strategies take the same span for a second reason: it is what makes
|
|
102
|
+
* a refusal reason mean the same thing under every strategy. A turn that ends
|
|
103
|
+
* the span this iteration is retried the next one — by which time the tool
|
|
104
|
+
* result it was waiting on has usually arrived.
|
|
91
105
|
*
|
|
92
|
-
* @param turns
|
|
93
|
-
* @param keepRecent
|
|
94
|
-
* @param
|
|
95
|
-
* @param
|
|
106
|
+
* @param turns the window's turn segmentation
|
|
107
|
+
* @param keepRecent how many trailing turns are off-limits
|
|
108
|
+
* @param guards what must not leave (unanswered calls, the pause)
|
|
109
|
+
* @param isExistingSummary optional: true for a turn that is a summary a prior
|
|
110
|
+
* fold wrote. When the whole span is one such turn, the plan refuses with
|
|
111
|
+
* `only-existing-summary` — re-summarizing a summary spends an LLM call to
|
|
112
|
+
* lose detail. The drop strategies omit it: a drop spends nothing, so there
|
|
113
|
+
* is nothing to protect against.
|
|
96
114
|
*/
|
|
97
|
-
export function
|
|
115
|
+
export function planRemoval(turns, keepRecent, guards, isExistingSummary) {
|
|
98
116
|
const refusals = [];
|
|
99
117
|
const candidateCount = Math.max(0, turns.length - keepRecent);
|
|
100
118
|
for (let i = candidateCount; i < turns.length; i++) {
|
|
@@ -108,7 +126,7 @@ export function planFold(turns, keepRecent, ctx, isSummaryTurn) {
|
|
|
108
126
|
let to = -1;
|
|
109
127
|
for (let i = 0; i < candidateCount; i++) {
|
|
110
128
|
const turn = turns[i];
|
|
111
|
-
const reason = refusalFor(turn,
|
|
129
|
+
const reason = refusalFor(turn, guards);
|
|
112
130
|
if (reason === undefined) {
|
|
113
131
|
if (from === -1)
|
|
114
132
|
from = i;
|
|
@@ -117,12 +135,16 @@ export function planFold(turns, keepRecent, ctx, isSummaryTurn) {
|
|
|
117
135
|
}
|
|
118
136
|
before.push({ reason, turnIndex: i, messageIndex: turn.start });
|
|
119
137
|
if (from !== -1)
|
|
120
|
-
break; // an
|
|
138
|
+
break; // an unremovable turn ENDS the span
|
|
121
139
|
}
|
|
122
140
|
// A span that is nothing but one existing summary is not worth a call:
|
|
123
141
|
// re-summarizing a summary spends tokens to lose detail and names nothing
|
|
124
142
|
// new. It becomes foldable again as soon as a real turn joins it.
|
|
125
|
-
|
|
143
|
+
const summaryOnly = isExistingSummary !== undefined &&
|
|
144
|
+
from !== -1 &&
|
|
145
|
+
from === to &&
|
|
146
|
+
isExistingSummary(turns[from]);
|
|
147
|
+
if (summaryOnly) {
|
|
126
148
|
return {
|
|
127
149
|
from: -1,
|
|
128
150
|
to: -1,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turns.js","sourceRoot":"","sources":["../../../../../src/core/agent/window/turns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAoBH;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAA8B;IACzD,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,OAAO,GAAiB,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACtF,OAAO,GAAG,EAAE,CAAC;IACf,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QACxB,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,KAAK,EAAE,CAAC;YACR,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IACD,KAAK,EAAE,CAAC;IACR,OAAO,KAAK,CAAC;AACf,CAAC;AAiBD,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,OAA8B;IAC5D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU;YAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,MAAqB;IAC1D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,iBAAiB,CAAC;IACtD,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,WAAW,GACf,GAAG,CAAC,UAAU,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;YACpF,IAAI,WAAW;gBAAE,OAAO,MAAM,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,aAAa,CAAC;QAC7F,CAAC;IACH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,OAAO,sBAAsB,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAWD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,WAAW,CACzB,KAAsB,EACtB,UAAkB,EAClB,MAAqB,EACrB,iBAA2C;IAE3C,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IAE9D,KAAK,IAAI,CAAC,GAAG,cAAc,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,oBAAoB,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,cAAc,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;IAEhE,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACd,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,IAAI,KAAK,CAAC,CAAC;gBAAE,IAAI,GAAG,CAAC,CAAC;YAC1B,EAAE,GAAG,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAChE,IAAI,IAAI,KAAK,CAAC,CAAC;YAAE,MAAM,CAAC,oCAAoC;IAC9D,CAAC;IAED,uEAAuE;IACvE,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM,WAAW,GACf,iBAAiB,KAAK,SAAS;QAC/B,IAAI,KAAK,CAAC,CAAC;QACX,IAAI,KAAK,EAAE;QACX,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAE,CAAC,CAAC;IAClC,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO;YACL,IAAI,EAAE,CAAC,CAAC;YACR,EAAE,EAAE,CAAC,CAAC;YACN,QAAQ,EAAE;gBACR,GAAG,MAAM;gBACT,EAAE,MAAM,EAAE,uBAAuB,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,IAAI,CAAE,CAAC,KAAK,EAAE;gBACtF,GAAG,QAAQ;aACZ;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CAAC,OAA8B;IACxD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,GAAG,IAAI,OAAO;QAAE,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;IACvD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* window/types — what each window strategy accepts, and what it writes into
|
|
3
|
+
* the ledger.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Value objects (no behavior) + resolved-config types.
|
|
6
|
+
* Role: core/ layer. The law this whole folder exists to keep is stated
|
|
7
|
+
* once, here, because every other file implements a piece of it:
|
|
8
|
+
* **a window strategy edits the WINDOW, never the LEDGER.**
|
|
9
|
+
* Emits: N/A (types only).
|
|
10
|
+
*
|
|
11
|
+
* The window is `scope.history` — the array `call-llm` hands the provider.
|
|
12
|
+
* The ledger is footprintjs's commit log, which is append-only: the turns a
|
|
13
|
+
* strategy removes from the window were committed by `seed#0` /
|
|
14
|
+
* `tool-calls#N` BEFORE the removal and stay in those bundles byte-identical
|
|
15
|
+
* forever. A strategy therefore cannot destroy history even in principle; it
|
|
16
|
+
* can only stop re-sending it. A summary is a CLAIM about the past, so it is
|
|
17
|
+
* filed as a claim — its own recorded step, naming every `runtimeStageId` it
|
|
18
|
+
* folded. A drop is an ABSENCE, and it is filed the same way: the record and
|
|
19
|
+
* the eviction events name what left, by id.
|
|
20
|
+
*/
|
|
21
|
+
import type { LLMProvider } from '../../../adapters/types.js';
|
|
22
|
+
/**
|
|
23
|
+
* Why a turn refused to leave the window. Every one of these is NAMED in the
|
|
24
|
+
* commit — a removal that took less than it could have has to say why, or the
|
|
25
|
+
* next person debugging an oversized window has to guess.
|
|
26
|
+
*
|
|
27
|
+
* The set is closed and shared: the same reason means the same thing under
|
|
28
|
+
* every strategy, because every strategy resolves it through the same
|
|
29
|
+
* function (`refusalFor`, bound into `WindowStrategyInput.planRemoval`).
|
|
30
|
+
*/
|
|
31
|
+
export type WindowRefusalReason =
|
|
32
|
+
/** The turn holds a `role: 'system'` message. The envelope never leaves. */
|
|
33
|
+
'system-envelope'
|
|
34
|
+
/**
|
|
35
|
+
* An assistant `tool_use` in this turn has no matching `tool_result` in the
|
|
36
|
+
* window. Removing an unanswered question destroys the answer's referent —
|
|
37
|
+
* and the referent may still arrive (a paused run resumes).
|
|
38
|
+
*/
|
|
39
|
+
| 'unresolved-tool-call'
|
|
40
|
+
/** The turn holds the tool call this run is currently paused on. */
|
|
41
|
+
| 'paused-tool'
|
|
42
|
+
/** The turn holds a tool call waiting on a human check-in decision. */
|
|
43
|
+
| 'pending-check-in'
|
|
44
|
+
/** Inside `keepRecentTurns` — the recent window is never a candidate. */
|
|
45
|
+
| 'inside-keep-window'
|
|
46
|
+
/**
|
|
47
|
+
* The only removable candidate is a summary a previous fold wrote. Folding
|
|
48
|
+
* a summary of a summary with nothing new to add spends a call to lose
|
|
49
|
+
* detail. Only `summarizeOldest` can report this: a drop spends nothing.
|
|
50
|
+
*/
|
|
51
|
+
| 'only-existing-summary'
|
|
52
|
+
/** The summarizer threw. No fold this iteration; the window stays big. */
|
|
53
|
+
| 'summarizer-failed'
|
|
54
|
+
/**
|
|
55
|
+
* The REPLACEMENT came back no smaller than the span it would replace, so
|
|
56
|
+
* the removal was abandoned. Both sides are measured in chars — the same
|
|
57
|
+
* unit, an exact comparison, not a token guess.
|
|
58
|
+
*
|
|
59
|
+
* For `summarizeOldest` the replacement is the summary message: folding
|
|
60
|
+
* here would spend a call to make the window BIGGER and lose the detail as
|
|
61
|
+
* well. For the drop strategies it is the authored drop notice that has to
|
|
62
|
+
* take the window's head position (see `DROP_NOTICE_PREFIX`): dropping two
|
|
63
|
+
* tiny turns to insert a longer notice is pure loss, so it does not happen.
|
|
64
|
+
*/
|
|
65
|
+
| 'summary-not-smaller';
|
|
66
|
+
/** One named refusal, positioned so a reader can find the turn. */
|
|
67
|
+
export interface WindowRefusal {
|
|
68
|
+
readonly reason: WindowRefusalReason;
|
|
69
|
+
/** Index of the turn in this iteration's turn segmentation. */
|
|
70
|
+
readonly turnIndex: number;
|
|
71
|
+
/** Index of the turn's first message in the pre-removal window. */
|
|
72
|
+
readonly messageIndex: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated Renamed to {@link WindowRefusal} in 7.17 — refusals are shared
|
|
76
|
+
* by every window strategy, and only one of them folds. This alias is the
|
|
77
|
+
* same type and is not going away in 7.x.
|
|
78
|
+
*/
|
|
79
|
+
export type FoldRefusal = WindowRefusal;
|
|
80
|
+
/**
|
|
81
|
+
* @deprecated Renamed to {@link WindowRefusalReason} in 7.17. Same values,
|
|
82
|
+
* same meanings; kept as an alias for code written against 7.16.
|
|
83
|
+
*/
|
|
84
|
+
export type FoldRefusalReason = WindowRefusalReason;
|
|
85
|
+
/**
|
|
86
|
+
* What one visit to the window stage put in the ledger.
|
|
87
|
+
*
|
|
88
|
+
* Every strategy files one of these — including the visits that removed
|
|
89
|
+
* NOTHING, which are the interesting ones. They are appended to
|
|
90
|
+
* `scope.compactions`, so the run's whole window story is one array in the
|
|
91
|
+
* commit log.
|
|
92
|
+
*
|
|
93
|
+
* (`compactions` is the key `.compaction()` shipped with in 7.16 and the key
|
|
94
|
+
* every strategy still writes: it is committed state, which is public surface
|
|
95
|
+
* for anyone reading a run, and renaming it for a better word would break
|
|
96
|
+
* those readers for nothing. It is named for the family's first member.)
|
|
97
|
+
*
|
|
98
|
+
* On `windowChars*` vs tokens: the char counts are EXACT and measured here.
|
|
99
|
+
* There is deliberately no `tokensAfter` — nothing can count the tokens of a
|
|
100
|
+
* window that has not been sent yet, and inventing one would be exactly the
|
|
101
|
+
* guess this family exists to refuse. The honest "after" is the NEXT call's
|
|
102
|
+
* `stream.llm_end` usage.
|
|
103
|
+
*/
|
|
104
|
+
export interface WindowRecord {
|
|
105
|
+
/**
|
|
106
|
+
* `WindowStrategy.name` of the strategy that decided — `'summarize-oldest'`,
|
|
107
|
+
* `'sliding-window'`, `'token-budget'`, or your own. Narrow on it.
|
|
108
|
+
*/
|
|
109
|
+
readonly strategy: string;
|
|
110
|
+
/** ReAct iteration this visit belongs to. */
|
|
111
|
+
readonly iteration: number;
|
|
112
|
+
/** `runtimeStageId`s of the stages that appended the messages that left. */
|
|
113
|
+
readonly removedStageIds: readonly string[];
|
|
114
|
+
/** How many messages left the window. */
|
|
115
|
+
readonly removedMessageCount: number;
|
|
116
|
+
/** Window size in chars before / after this visit. Exact, and not tokens. */
|
|
117
|
+
readonly windowCharsBefore: number;
|
|
118
|
+
readonly windowCharsAfter: number;
|
|
119
|
+
/** Every turn that refused to leave, named. */
|
|
120
|
+
readonly refusals: readonly WindowRefusal[];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* What one OVER-BUDGET visit to `summarizeOldest` (what `.compaction()`
|
|
124
|
+
* configures) put in the ledger.
|
|
125
|
+
*/
|
|
126
|
+
export interface CompactionRecord extends WindowRecord {
|
|
127
|
+
/** Adapter-reported input tokens of the last call — what tripped the check. */
|
|
128
|
+
readonly measuredTokens: number;
|
|
129
|
+
/** The budget it was compared against. */
|
|
130
|
+
readonly thresholdTokens: number;
|
|
131
|
+
/** True when the measurement was over budget (a fold was attempted). */
|
|
132
|
+
readonly overBudget: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* @deprecated Use {@link WindowRecord.removedStageIds} — the family name for
|
|
135
|
+
* the same value, published alongside it since 7.17. Both are written.
|
|
136
|
+
*/
|
|
137
|
+
readonly foldedStageIds: readonly string[];
|
|
138
|
+
/**
|
|
139
|
+
* @deprecated Use {@link WindowRecord.removedMessageCount} — the family name
|
|
140
|
+
* for the same value, published alongside it since 7.17. Both are written.
|
|
141
|
+
*/
|
|
142
|
+
readonly foldedMessageCount: number;
|
|
143
|
+
/** Length of the summary text the summarizer produced (0 when none). */
|
|
144
|
+
readonly summaryChars: number;
|
|
145
|
+
/** What the summarizer call itself cost, when it reported usage. */
|
|
146
|
+
readonly summarizerTokens?: {
|
|
147
|
+
readonly input: number;
|
|
148
|
+
readonly output: number;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** What one visit to `slidingWindow` put in the ledger. */
|
|
152
|
+
export interface SlidingWindowRecord extends WindowRecord {
|
|
153
|
+
readonly strategy: 'sliding-window';
|
|
154
|
+
/** The configured keep depth this visit measured against. */
|
|
155
|
+
readonly keepRecentTurns: number;
|
|
156
|
+
/** Turns in the window before / after this visit. Counted, not estimated. */
|
|
157
|
+
readonly turnsBefore: number;
|
|
158
|
+
readonly turnsAfter: number;
|
|
159
|
+
}
|
|
160
|
+
/** What one OVER-BUDGET visit to `tokenBudget` put in the ledger. */
|
|
161
|
+
export interface TokenBudgetRecord extends WindowRecord {
|
|
162
|
+
readonly strategy: 'token-budget';
|
|
163
|
+
/** Adapter-reported input tokens of the last call — what tripped the check. */
|
|
164
|
+
readonly measuredTokens: number;
|
|
165
|
+
/** The budget it was compared against. */
|
|
166
|
+
readonly thresholdTokens: number;
|
|
167
|
+
/** True when the measurement was over budget (a drop was attempted). */
|
|
168
|
+
readonly overBudget: boolean;
|
|
169
|
+
/** How many recent turns were off-limits to this visit. */
|
|
170
|
+
readonly keepRecentTurns: number;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* What `.compaction({...})` — and `summarizeOldest({...})` — accepts.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* const agent = Agent.create({ provider: anthropic(), model: 'claude-sonnet-4-5' })
|
|
178
|
+
* .compaction({
|
|
179
|
+
* thresholdTokens: 120_000,
|
|
180
|
+
* summarizer: anthropic(), // usually the cheap one
|
|
181
|
+
* model: 'claude-haiku-4-5',
|
|
182
|
+
* keepRecentTurns: 6,
|
|
183
|
+
* })
|
|
184
|
+
* .build();
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
export interface CompactionOptions {
|
|
188
|
+
/**
|
|
189
|
+
* Fold when the LAST call's adapter-reported input tokens exceed this.
|
|
190
|
+
*
|
|
191
|
+
* REQUIRED, with no default. A default budget here would be a number the
|
|
192
|
+
* library invented for a window whose size only the consumer's model and
|
|
193
|
+
* wallet know — and every run would silently inherit it.
|
|
194
|
+
*/
|
|
195
|
+
readonly thresholdTokens: number;
|
|
196
|
+
/**
|
|
197
|
+
* How many of the most recent turns are never folded. Default 6.
|
|
198
|
+
*
|
|
199
|
+
* The recent turns are what the model is actually reasoning over; folding
|
|
200
|
+
* them is how a compacting agent loses the thread.
|
|
201
|
+
*/
|
|
202
|
+
readonly keepRecentTurns?: number;
|
|
203
|
+
/**
|
|
204
|
+
* The provider that writes the summary. Explicitly chosen — the library
|
|
205
|
+
* never quietly bills your main model for compaction.
|
|
206
|
+
*/
|
|
207
|
+
readonly summarizer: LLMProvider;
|
|
208
|
+
/**
|
|
209
|
+
* Model id for the summarizer call. Defaults to the agent's own model, so
|
|
210
|
+
* `summarizer: anthropic()` alone works; name a cheap model to spend less.
|
|
211
|
+
*/
|
|
212
|
+
readonly model?: string;
|
|
213
|
+
}
|
|
214
|
+
/** Resolved form — defaults applied at build time, validated once. */
|
|
215
|
+
export interface ResolvedCompaction {
|
|
216
|
+
readonly thresholdTokens: number;
|
|
217
|
+
readonly keepRecentTurns: number;
|
|
218
|
+
readonly summarizer: LLMProvider;
|
|
219
|
+
readonly model: string | undefined;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* What `slidingWindow({...})` accepts.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* const agent = Agent.create({ provider: anthropic(), model: 'claude-sonnet-4-5' })
|
|
227
|
+
* .window(slidingWindow({ keepRecentTurns: 12 }))
|
|
228
|
+
* .build();
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
export interface SlidingWindowOptions {
|
|
232
|
+
/**
|
|
233
|
+
* How many of the most recent turns stay in the window. Everything older is
|
|
234
|
+
* dropped — unless it refuses by name.
|
|
235
|
+
*
|
|
236
|
+
* REQUIRED, with no default. It *is* the policy: how much past this agent
|
|
237
|
+
* needs is a fact about your agent, not about this library.
|
|
238
|
+
*/
|
|
239
|
+
readonly keepRecentTurns: number;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* What `tokenBudget({...})` accepts.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* const agent = Agent.create({ provider: anthropic(), model: 'claude-sonnet-4-5' })
|
|
247
|
+
* .window(tokenBudget({ thresholdTokens: 120_000 }))
|
|
248
|
+
* .build();
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
export interface TokenBudgetOptions {
|
|
252
|
+
/**
|
|
253
|
+
* Drop when the LAST call's adapter-reported input tokens exceed this.
|
|
254
|
+
*
|
|
255
|
+
* REQUIRED, with no default — the same reason as `.compaction()`: only your
|
|
256
|
+
* model and your bill know the right number.
|
|
257
|
+
*/
|
|
258
|
+
readonly thresholdTokens: number;
|
|
259
|
+
/**
|
|
260
|
+
* How many of the most recent turns are never dropped. Default 6.
|
|
261
|
+
*/
|
|
262
|
+
readonly keepRecentTurns?: number;
|
|
263
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* window/types — what each window strategy accepts, and what it writes into
|
|
3
|
+
* the ledger.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Value objects (no behavior) + resolved-config types.
|
|
6
|
+
* Role: core/ layer. The law this whole folder exists to keep is stated
|
|
7
|
+
* once, here, because every other file implements a piece of it:
|
|
8
|
+
* **a window strategy edits the WINDOW, never the LEDGER.**
|
|
9
|
+
* Emits: N/A (types only).
|
|
10
|
+
*
|
|
11
|
+
* The window is `scope.history` — the array `call-llm` hands the provider.
|
|
12
|
+
* The ledger is footprintjs's commit log, which is append-only: the turns a
|
|
13
|
+
* strategy removes from the window were committed by `seed#0` /
|
|
14
|
+
* `tool-calls#N` BEFORE the removal and stay in those bundles byte-identical
|
|
15
|
+
* forever. A strategy therefore cannot destroy history even in principle; it
|
|
16
|
+
* can only stop re-sending it. A summary is a CLAIM about the past, so it is
|
|
17
|
+
* filed as a claim — its own recorded step, naming every `runtimeStageId` it
|
|
18
|
+
* folded. A drop is an ABSENCE, and it is filed the same way: the record and
|
|
19
|
+
* the eviction events name what left, by id.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/core/agent/window/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export { LLMCall, LLMCallBuilder, type LLMCallInput, type LLMCallOptions, type L
|
|
|
27
27
|
export { type MessageApiChartDeps } from './core/agent/buildMessageApiChart.js';
|
|
28
28
|
export { buildAgentMessageApiChart, type AgentMessageApiChartDeps, } from './core/agent/buildAgentMessageApiChart.js';
|
|
29
29
|
export { Agent, AgentBuilder, type AgentInput, type AgentOptions, type AgentOutput, type ObserverDeliveryOptions, } from './core/Agent.js';
|
|
30
|
-
export { CompactionUnmeasurableError, COMPACTED_FRAME_PREFIX, isCompactedSummary, type CompactionOptions, type CompactionRecord, type FoldRefusal, type FoldRefusalReason, } from './core/agent/
|
|
30
|
+
export { CompactionUnmeasurableError, COMPACTED_FRAME_PREFIX, DROP_NOTICE_PREFIX, isCompactedSummary, isDropNotice, slidingWindow, summarizeOldest, tokenBudget, type CompactionOptions, type CompactionRecord, type FoldRefusal, type FoldRefusalReason, type RemovalFacts, type RemovalPlan, type SlidingWindowOptions, type SlidingWindowRecord, type TokenBudgetOptions, type TokenBudgetRecord, type Turn, type WindowEviction, type WindowRecord, type WindowRefusal, type WindowRefusalReason, type WindowStrategy, type WindowStrategyInput, type WindowStrategyResult, } from './core/agent/window/index.js';
|
|
31
31
|
export type { SelfExplainOptions } from './lib/trace-toolpack/selfExplain.js';
|
|
32
32
|
export type { ObserverDrainResult, ObserverStats } from 'footprintjs';
|
|
33
33
|
export type { ToolArgValidationMode } from './core/agent/toolArgsValidation.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -84,11 +84,16 @@ export { LLMCall, LLMCallBuilder, } from './core/LLMCall.js';
|
|
|
84
84
|
// only additions over buildMessageApiChart. See buildAgentMessageApiChart.
|
|
85
85
|
export { buildAgentMessageApiChart, } from './core/agent/buildAgentMessageApiChart.js';
|
|
86
86
|
export { Agent, AgentBuilder, } from './core/Agent.js';
|
|
87
|
-
// `.compaction()` — keep the live window inside
|
|
88
|
-
// losing the record.
|
|
89
|
-
// turn byte-identical, and
|
|
90
|
-
//
|
|
91
|
-
|
|
87
|
+
// `.window(strategy)` / `.compaction()` — keep the live context window inside
|
|
88
|
+
// its budget without ever losing the record. A strategy edits the WINDOW; the
|
|
89
|
+
// LEDGER keeps every removed turn byte-identical, and every strategy files its
|
|
90
|
+
// own recorded step naming the runtimeStageIds whose messages left.
|
|
91
|
+
//
|
|
92
|
+
// Three ship, over one turn segmentation and one refusal engine:
|
|
93
|
+
// summarizeOldest fold the oldest span into a summary (what `.compaction()` is)
|
|
94
|
+
// slidingWindow keep the last N turns, drop older ones
|
|
95
|
+
// tokenBudget counted-token trigger, drop instead of summarize
|
|
96
|
+
export { CompactionUnmeasurableError, COMPACTED_FRAME_PREFIX, DROP_NOTICE_PREFIX, isCompactedSummary, isDropNotice, slidingWindow, summarizeOldest, tokenBudget, } from './core/agent/window/index.js';
|
|
92
97
|
export { OutputSchemaError, applyOutputSchema, } from './core/outputSchema.js';
|
|
93
98
|
export { RunCheckpointError } from './core/runCheckpoint.js';
|
|
94
99
|
export { flowchartAsTool, } from './core/flowchartAsTool.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oEAAoE;AACpE,8DAA8D;AAC9D,uEAAuE;AACvE,kEAAkE;AAClE,sEAAsE;AACtE,sDAAsD;AACtD,OAAO,8CAA8C,CAAC;AACtD,OAAO,2CAA2C,CAAC;AACnD,OAAO,4CAA4C,CAAC;AAsCpD,6BAA6B;AAC7B,cAAc,qBAAqB,CAAC;AAEpC,yEAAyE;AACzE,uDAAuD;AACvD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,cAAc;AAEd,yEAAyE;AACzE,wEAAwE;AACxE,yEAAyE;AACzE,gBAAgB;AAChB,SAAS;AAET,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,6DAA6D;AAC7D,YAAY,GAGb,MAAM,kBAAkB,CAAC;AAC1B,oEAAoE;AACpE,yEAAyE;AACzE,wEAAwE;AACxE,qEAAqE;AACrE,kDAAkD;AAClD,OAAO,EACL,gBAAgB,GAMjB,MAAM,2BAA2B,CAAC;AAKnC,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AACzE,kEAAkE;AAClE,oEAAoE;AACpE,qEAAqE;AACrE,2EAA2E;AAC3E,8EAA8E;AAC9E,0DAA0D;AAC1D,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,GAKjB,MAAM,wCAAwC,CAAC;AAIhD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAO7D,sEAAsE;AACtE,wEAAwE;AACxE,iEAAiE;AACjE,sEAAsE;AACtE,uEAAuE;AACvE,OAAO,EACL,SAAS,EACT,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,cAAc,GAEf,MAAM,iBAAiB,CAAC;AAEzB,uEAAuE;AACvE,6EAA6E;AAC7E,mEAAmE;AACnE,0EAA0E;AAC1E,oFAAoF;AACpF,OAAO,EACL,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,GAgBzB,MAAM,mBAAmB,CAAC;AAM3B,6EAA6E;AAC7E,OAAO,EACL,eAAe,GAIhB,MAAM,qCAAqC,CAAC;AAY7C,qEAAqE;AACrE,kEAAkE;AAClE,kEAAkE;AAClE,OAAO,EACL,0BAA0B;AAC1B,kEAAkE;AAClE,mEAAmE;AACnE,oDAAoD;AACpD,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,6DAA6D,CAAC;AAErE,gEAAgE;AAChE,sEAAsE;AACtE,uDAAuD;AACvD,sEAAsE;AACtE,+DAA+D;AAC/D,gEAAgE;AAChE,wEAAwE;AACxE,mCAAmC;AAEnC,qBAAqB;AACrB,OAAO,EACL,OAAO,EACP,cAAc,GAIf,MAAM,mBAAmB,CAAC;AAO3B,2EAA2E;AAC3E,gFAAgF;AAChF,4EAA4E;AAC5E,2EAA2E;AAC3E,OAAO,EACL,yBAAyB,GAE1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,KAAK,EACL,YAAY,GAKb,MAAM,iBAAiB,CAAC;AACzB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|