goatchain 0.0.31 → 0.0.33

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.
@@ -3,48 +3,196 @@ import type { AgentLoopState } from '../agent/types';
3
3
  import type { ModelClient } from '../model';
4
4
  import type { StateStore } from '../state/stateStore';
5
5
  import type { Message } from '../types';
6
+ /**
7
+ * Configuration options for context compression middleware.
8
+ */
6
9
  export interface ContextCompressionOptions {
7
- contextLength: number;
10
+ /**
11
+ * Maximum token limit for the model (e.g., 128000 for GPT-4).
12
+ * - Tool compression triggers at 50% (maxTokens * 0.5)
13
+ * - Summary compression triggers at 80% (maxTokens * 0.8)
14
+ */
15
+ maxTokens: number;
16
+ /**
17
+ * Compression strategy mode.
18
+ * - `smart` (default): use adaptive boundaries and multi-stage compression.
19
+ * - `legacy`: keep historical behavior based on `protectedTurns` and tool params.
20
+ */
21
+ compressionMode?: 'smart' | 'legacy';
22
+ /**
23
+ * Number of recent conversation turns to always protect (default: 2, legacy mode only).
24
+ * A turn is a user message + assistant response pair.
25
+ * The last N turns will always be preserved from summary compression.
26
+ * Tool compression ignores this setting and only preserves tool results from
27
+ * the most recent completed turn.
28
+ *
29
+ * @deprecated Use smart mode (default) instead.
30
+ */
31
+ protectedTurns?: number;
32
+ /**
33
+ * Model to use for generating summaries.
34
+ */
35
+ model: ModelClient;
36
+ /**
37
+ * State store for persisting compression state.
38
+ */
39
+ stateStore: StateStore;
40
+ /**
41
+ * Tool compression target (default: 0.45, meaning compress to 45% of maxTokens).
42
+ * When tool compression is triggered at 50%, it will compress until reaching this target.
43
+ *
44
+ * @deprecated Use smart mode (default) instead.
45
+ */
46
+ toolCompressionTarget?: number;
47
+ /**
48
+ * Minimum number of recent tool results to keep (default: 5, legacy mode only).
49
+ * The most recent N tool results will be protected from compression.
50
+ *
51
+ * @deprecated Use smart mode (default) instead.
52
+ */
53
+ minKeepToolResults?: number;
54
+ /**
55
+ * Enable logging compression events to a file in the current working directory.
56
+ * If enabled, logs will be appended to 'compression-logs.jsonl' in JSONL format.
57
+ */
58
+ enableLogging?: boolean;
59
+ /**
60
+ * Custom log file path (relative to cwd or absolute).
61
+ * Default: 'compression-logs.jsonl'
62
+ */
63
+ logFilePath?: string;
64
+ /**
65
+ * Token limit of the model used for summarization.
66
+ * Used to determine when chunked summarization is needed.
67
+ * When the content to summarize exceeds this limit, the middleware
68
+ * automatically splits it into chunks and summarizes sequentially.
69
+ * Defaults to maxTokens if not specified.
70
+ */
71
+ summaryModelMaxTokens?: number;
72
+ /**
73
+ * Maximum characters per individual message when formatting for summary.
74
+ * More aggressive truncation reduces the chance of needing chunked summarization.
75
+ * Applies to tool outputs, user messages, and assistant messages.
76
+ * Default: 3000
77
+ */
78
+ maxMessageCharsForSummary?: number;
8
79
  }
80
+ /**
81
+ * Options for manual compression.
82
+ */
9
83
  export interface ManualCompressionOptions {
84
+ /**
85
+ * Session ID for the compression.
86
+ */
10
87
  sessionId: string;
88
+ /**
89
+ * Full messages from the session (including all history).
90
+ * These should be the complete, uncompressed messages.
91
+ */
11
92
  fullMessages: Message[];
93
+ /**
94
+ * Model to use for generating summary.
95
+ */
12
96
  model: ModelClient;
97
+ /**
98
+ * State store for persisting compression state.
99
+ */
13
100
  stateStore: StateStore;
14
- contextLength: number;
101
+ /**
102
+ * Custom prompt for summary generation (optional).
103
+ * If not provided, uses DEFAULT_SUMMARY_PROMPT.
104
+ */
105
+ summaryPrompt?: string;
106
+ /**
107
+ * Enable logging compression events to a file.
108
+ */
109
+ enableLogging?: boolean;
110
+ /**
111
+ * Custom log file path (relative to cwd or absolute).
112
+ * Default: 'compression-logs.jsonl'
113
+ */
114
+ logFilePath?: string;
115
+ /**
116
+ * Token limit of the model used for summarization.
117
+ * Used to determine when chunked summarization is needed.
118
+ * Defaults to 128000 if not specified.
119
+ */
120
+ summaryModelMaxTokens?: number;
121
+ /**
122
+ * Maximum characters per individual message when formatting for summary.
123
+ * Default: 3000
124
+ */
125
+ maxMessageCharsForSummary?: number;
15
126
  }
127
+ /**
128
+ * Result of manual compression.
129
+ */
16
130
  export interface ManualCompressionResult {
131
+ /**
132
+ * Generated summary.
133
+ */
17
134
  summary: string;
135
+ /**
136
+ * Number of messages processed.
137
+ */
18
138
  messageCount: number;
139
+ /**
140
+ * Number of tool outputs found.
141
+ */
19
142
  toolOutputCount: number;
143
+ /**
144
+ * Committed compressed working view including the system message.
145
+ */
20
146
  compressedMessages: Message[];
21
147
  }
148
+ /**
149
+ * Statistics about the compression operation.
150
+ */
22
151
  export interface CompressionStats {
152
+ /** Token count before compression */
23
153
  tokensBefore: number;
154
+ /** Token count after compression */
24
155
  tokensAfter: number;
156
+ /** Number of tool outputs that were cleared */
25
157
  clearedToolOutputs: number;
158
+ /** Number of messages that were removed by summarization */
26
159
  removedMessages: number;
160
+ /** Whether a summary was generated */
27
161
  summaryGenerated: boolean;
162
+ /** Timestamp when this compression occurred */
28
163
  timestamp: number;
29
164
  }
30
- export type CompressionTraceStage = 'stage1' | 'stage2' | 'stage3' | 'stage4';
31
- export interface CompressionTraceSnapshot {
32
- sessionId: string;
33
- mode: CompressionMode;
34
- stage: CompressionTraceStage;
35
- contextLength: number;
36
- triggerThreshold: number;
37
- targetTokens: number;
38
- tokens: number;
39
- messages: Message[];
40
- rawMessages: Message[];
41
- summary: string;
42
- coveredMessageCount: number;
43
- clearedToolOutputs: number;
44
- removedMessages: number;
45
- summaryGenerated: boolean;
46
- }
47
- type CompressionMode = 'auto' | 'manual';
165
+ /**
166
+ * Create a context compression middleware.
167
+ *
168
+ * This middleware automatically compresses conversation history.
169
+ *
170
+ * Smart mode uses a target-driven flow:
171
+ * - Triggers summary compression near 80% of maxTokens
172
+ * - Compresses toward a low-water target near 30% in the same iteration
173
+ * - Bounds the persisted rolling summary so it cannot silently grow forever
174
+ * - Applies cooldown to avoid repeated re-summary on tiny growth
175
+ * - Bypasses cooldown in emergency overflow cases, then hard-fails before model
176
+ * invocation if the prompt still cannot fit within maxTokens
177
+ *
178
+ * Legacy mode keeps the historical protected-turn / protected-tool behavior.
179
+ *
180
+ * @param options - Compression configuration options
181
+ * @returns Middleware function
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * const agent = new Agent({ model, stateStore, ... })
186
+ *
187
+ * agent.use(createContextCompressionMiddleware({
188
+ * maxTokens: 128000,
189
+ * model: model,
190
+ * stateStore: agent.stateStore,
191
+ * }))
192
+ * ```
193
+ */
48
194
  export declare function createContextCompressionMiddleware(options: ContextCompressionOptions): Middleware<AgentLoopState>;
195
+ /**
196
+ * Manually compress a session by generating a summary from full message history.
197
+ */
49
198
  export declare function compressSessionManually(options: ManualCompressionOptions): Promise<ManualCompressionResult>;
50
- export {};
@@ -60,12 +60,64 @@ export interface CompressedMessagesSnapshot {
60
60
  * allowing the middleware to restore its state after a restart.
61
61
  */
62
62
  export interface CompressionState {
63
+ /**
64
+ * Statistics from the last compression operation.
65
+ */
63
66
  lastStats?: CompressionStats;
67
+ /**
68
+ * History of all compression operations.
69
+ */
70
+ history: CompressionStats[];
71
+ /**
72
+ * Rolling summary content from summarized messages.
73
+ * This can be used when resuming from a checkpoint to provide context.
74
+ */
64
75
  summary?: string;
65
- coveredMessageCount?: number;
66
- baseRawSignature?: string;
67
- baseRawMessageCount?: number;
76
+ /**
77
+ * Timestamp of the last smart-mode summary compression (ms).
78
+ */
79
+ lastSummaryAt?: number;
80
+ /**
81
+ * Estimated token count before the last persisted summary compression.
82
+ */
83
+ lastSummaryInputTokens?: number;
84
+ /**
85
+ * Estimated token count for the persisted summary view after the last summary
86
+ * compression, before any temporary tool-output clearing for the live LLM call.
87
+ */
88
+ lastSummaryOutputTokens?: number;
89
+ /**
90
+ * Number of messages removed by the last persisted summary compression.
91
+ */
92
+ lastSummaryRemovedMessages?: number;
93
+ /**
94
+ * Whether the persisted summary was rewritten to fit the bounded summary budget.
95
+ */
96
+ lastSummaryRewriteApplied?: boolean;
97
+ /**
98
+ * Last update timestamp (ms).
99
+ */
68
100
  updatedAt: number;
101
+ /**
102
+ * Record of which messages were compressed (removed) in the last summary compression.
103
+ * Used to remove the same messages when loading the summary on session resume.
104
+ */
105
+ compressedRange?: {
106
+ /**
107
+ * Index where summarization starts (first non-system message).
108
+ * Messages before this index (system messages) are always kept.
109
+ */
110
+ summarizeStart: number;
111
+ /**
112
+ * Index where protected turns start (messages from this onward are kept).
113
+ */
114
+ protectedStart: number;
115
+ /**
116
+ * Total number of messages at the time of compression.
117
+ * Used to validate if the range is still applicable.
118
+ */
119
+ totalMessagesAtCompression: number;
120
+ };
69
121
  }
70
122
  /**
71
123
  * Persisted compressed working view.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goatchain",
3
3
  "type": "module",
4
- "version": "0.0.31",
4
+ "version": "0.0.33",
5
5
  "workspaces": [
6
6
  "packages/*"
7
7
  ],