@compilr-dev/agents 0.1.0 → 0.2.1

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.
@@ -0,0 +1,156 @@
1
+ /**
2
+ * File Access Tracker
3
+ *
4
+ * Tracks file accesses during agent sessions to provide context restoration
5
+ * hints after compaction. Inspired by Claude Code's post-compaction file
6
+ * reference display.
7
+ *
8
+ * Features:
9
+ * - Track read, referenced, and modified files
10
+ * - Deduplication (read supersedes reference)
11
+ * - Max entries with LRU eviction
12
+ * - Verbosity-aware formatting
13
+ *
14
+ * @see /workspace/project-docs/00-requirements/compilr-dev-agents/context-restoration-hints.md
15
+ */
16
+ import type { VerbosityLevel } from './types.js';
17
+ /**
18
+ * Type of file access
19
+ */
20
+ export type FileAccessType = 'read' | 'referenced' | 'modified';
21
+ /**
22
+ * Record of a file access
23
+ */
24
+ export interface FileAccess {
25
+ /** Absolute file path */
26
+ path: string;
27
+ /** Type of access */
28
+ type: FileAccessType;
29
+ /** When accessed (timestamp) */
30
+ timestamp: number;
31
+ /** Number of lines (for 'read' type) */
32
+ lineCount?: number;
33
+ /** Optional summary of what was found/changed */
34
+ summary?: string;
35
+ }
36
+ /**
37
+ * Options for FileAccessTracker constructor
38
+ */
39
+ export interface FileAccessTrackerOptions {
40
+ /**
41
+ * Maximum number of entries to track
42
+ * @default 100
43
+ */
44
+ maxEntries?: number;
45
+ /**
46
+ * Deduplicate references (don't track same file twice as 'referenced')
47
+ * @default true
48
+ */
49
+ deduplicateReferences?: boolean;
50
+ }
51
+ /**
52
+ * Options for formatting restoration hints
53
+ */
54
+ export interface FormatHintsOptions {
55
+ /** Include line counts for read files @default true */
56
+ includeLineCount?: boolean;
57
+ /** Include summaries @default false */
58
+ includeSummary?: boolean;
59
+ /** Include timestamps @default false */
60
+ includeTimestamp?: boolean;
61
+ /** Group by access type @default true */
62
+ groupByType?: boolean;
63
+ /** Maximum files to include @default 20 */
64
+ maxFiles?: number;
65
+ /** Verbosity level (adjusts format automatically) */
66
+ verbosityLevel?: VerbosityLevel;
67
+ }
68
+ /**
69
+ * Statistics about file accesses
70
+ */
71
+ export interface FileAccessStats {
72
+ read: number;
73
+ referenced: number;
74
+ modified: number;
75
+ total: number;
76
+ }
77
+ /**
78
+ * Tracks file accesses during agent sessions for context restoration hints.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const tracker = new FileAccessTracker();
83
+ *
84
+ * // Track file accesses
85
+ * tracker.trackRead('/path/to/file.ts', 597);
86
+ * tracker.trackReference('/path/to/other.ts');
87
+ * tracker.trackModification('/path/to/file.ts', 'Added function');
88
+ *
89
+ * // Get restoration hints after compaction
90
+ * const hints = tracker.formatRestorationHints();
91
+ * console.log(hints);
92
+ * ```
93
+ */
94
+ export declare class FileAccessTracker {
95
+ private readonly accesses;
96
+ private readonly maxEntries;
97
+ private readonly deduplicateReferences;
98
+ constructor(options?: FileAccessTrackerOptions);
99
+ /**
100
+ * Track a file that was fully read
101
+ */
102
+ trackRead(filePath: string, lineCount: number, summary?: string): void;
103
+ /**
104
+ * Track a file that was referenced (e.g., appeared in grep/glob results)
105
+ */
106
+ trackReference(filePath: string): void;
107
+ /**
108
+ * Track a file that was modified (written or edited)
109
+ */
110
+ trackModification(filePath: string, summary?: string): void;
111
+ /**
112
+ * Get all file accesses, optionally filtered
113
+ */
114
+ getAccesses(options?: {
115
+ type?: FileAccessType;
116
+ since?: number;
117
+ }): FileAccess[];
118
+ /**
119
+ * Get most recent file accesses
120
+ */
121
+ getRecentAccesses(limit?: number): FileAccess[];
122
+ /**
123
+ * Check if a file has been accessed
124
+ */
125
+ hasAccessed(filePath: string): boolean;
126
+ /**
127
+ * Get access record for a specific file
128
+ */
129
+ getAccess(filePath: string): FileAccess | undefined;
130
+ /**
131
+ * Get statistics about file accesses
132
+ */
133
+ getStats(): FileAccessStats;
134
+ /**
135
+ * Format restoration hints for injection after compaction
136
+ */
137
+ formatRestorationHints(options?: FormatHintsOptions): string;
138
+ /**
139
+ * Clear all tracked accesses
140
+ */
141
+ clear(): void;
142
+ /**
143
+ * Get the number of tracked files
144
+ */
145
+ get size(): number;
146
+ private normalizePath;
147
+ private enforceMaxEntries;
148
+ private getEffectiveMaxFiles;
149
+ private formatCompact;
150
+ private formatGrouped;
151
+ private formatFlat;
152
+ private formatAccessLine;
153
+ private groupByType;
154
+ private getDisplayName;
155
+ private getDisplayPath;
156
+ }
@@ -0,0 +1,358 @@
1
+ /**
2
+ * File Access Tracker
3
+ *
4
+ * Tracks file accesses during agent sessions to provide context restoration
5
+ * hints after compaction. Inspired by Claude Code's post-compaction file
6
+ * reference display.
7
+ *
8
+ * Features:
9
+ * - Track read, referenced, and modified files
10
+ * - Deduplication (read supersedes reference)
11
+ * - Max entries with LRU eviction
12
+ * - Verbosity-aware formatting
13
+ *
14
+ * @see /workspace/project-docs/00-requirements/compilr-dev-agents/context-restoration-hints.md
15
+ */
16
+ import path from 'path';
17
+ // ============================================================================
18
+ // FileAccessTracker Class
19
+ // ============================================================================
20
+ /**
21
+ * Tracks file accesses during agent sessions for context restoration hints.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const tracker = new FileAccessTracker();
26
+ *
27
+ * // Track file accesses
28
+ * tracker.trackRead('/path/to/file.ts', 597);
29
+ * tracker.trackReference('/path/to/other.ts');
30
+ * tracker.trackModification('/path/to/file.ts', 'Added function');
31
+ *
32
+ * // Get restoration hints after compaction
33
+ * const hints = tracker.formatRestorationHints();
34
+ * console.log(hints);
35
+ * ```
36
+ */
37
+ export class FileAccessTracker {
38
+ accesses = new Map();
39
+ maxEntries;
40
+ deduplicateReferences;
41
+ constructor(options = {}) {
42
+ this.maxEntries = options.maxEntries ?? 100;
43
+ this.deduplicateReferences = options.deduplicateReferences ?? true;
44
+ }
45
+ // ==========================================================================
46
+ // Track Methods
47
+ // ==========================================================================
48
+ /**
49
+ * Track a file that was fully read
50
+ */
51
+ trackRead(filePath, lineCount, summary) {
52
+ const normalizedPath = this.normalizePath(filePath);
53
+ // Read supersedes reference - remove any existing reference
54
+ const existing = this.accesses.get(normalizedPath);
55
+ if (existing && existing.type === 'referenced') {
56
+ this.accesses.delete(normalizedPath);
57
+ }
58
+ // Update or create read entry
59
+ this.accesses.set(normalizedPath, {
60
+ path: normalizedPath,
61
+ type: 'read',
62
+ timestamp: Date.now(),
63
+ lineCount,
64
+ summary,
65
+ });
66
+ this.enforceMaxEntries();
67
+ }
68
+ /**
69
+ * Track a file that was referenced (e.g., appeared in grep/glob results)
70
+ */
71
+ trackReference(filePath) {
72
+ const normalizedPath = this.normalizePath(filePath);
73
+ // Don't downgrade read/modified to reference
74
+ const existing = this.accesses.get(normalizedPath);
75
+ if (existing && (existing.type === 'read' || existing.type === 'modified')) {
76
+ return;
77
+ }
78
+ // Deduplicate references
79
+ if (this.deduplicateReferences && existing && existing.type === 'referenced') {
80
+ // Update timestamp only
81
+ existing.timestamp = Date.now();
82
+ return;
83
+ }
84
+ this.accesses.set(normalizedPath, {
85
+ path: normalizedPath,
86
+ type: 'referenced',
87
+ timestamp: Date.now(),
88
+ });
89
+ this.enforceMaxEntries();
90
+ }
91
+ /**
92
+ * Track a file that was modified (written or edited)
93
+ */
94
+ trackModification(filePath, summary) {
95
+ const normalizedPath = this.normalizePath(filePath);
96
+ this.accesses.set(normalizedPath, {
97
+ path: normalizedPath,
98
+ type: 'modified',
99
+ timestamp: Date.now(),
100
+ summary,
101
+ });
102
+ this.enforceMaxEntries();
103
+ }
104
+ // ==========================================================================
105
+ // Query Methods
106
+ // ==========================================================================
107
+ /**
108
+ * Get all file accesses, optionally filtered
109
+ */
110
+ getAccesses(options) {
111
+ let accesses = Array.from(this.accesses.values());
112
+ if (options?.type) {
113
+ accesses = accesses.filter((a) => a.type === options.type);
114
+ }
115
+ if (options?.since !== undefined) {
116
+ const since = options.since;
117
+ accesses = accesses.filter((a) => a.timestamp >= since);
118
+ }
119
+ // Sort by timestamp descending (most recent first)
120
+ return accesses.sort((a, b) => b.timestamp - a.timestamp);
121
+ }
122
+ /**
123
+ * Get most recent file accesses
124
+ */
125
+ getRecentAccesses(limit = 10) {
126
+ return this.getAccesses().slice(0, limit);
127
+ }
128
+ /**
129
+ * Check if a file has been accessed
130
+ */
131
+ hasAccessed(filePath) {
132
+ return this.accesses.has(this.normalizePath(filePath));
133
+ }
134
+ /**
135
+ * Get access record for a specific file
136
+ */
137
+ getAccess(filePath) {
138
+ return this.accesses.get(this.normalizePath(filePath));
139
+ }
140
+ /**
141
+ * Get statistics about file accesses
142
+ */
143
+ getStats() {
144
+ const stats = { read: 0, referenced: 0, modified: 0, total: 0 };
145
+ for (const access of this.accesses.values()) {
146
+ stats[access.type]++;
147
+ stats.total++;
148
+ }
149
+ return stats;
150
+ }
151
+ // ==========================================================================
152
+ // Format Methods
153
+ // ==========================================================================
154
+ /**
155
+ * Format restoration hints for injection after compaction
156
+ */
157
+ formatRestorationHints(options = {}) {
158
+ const { includeLineCount = true, includeSummary = false, includeTimestamp = false, groupByType = true, maxFiles = 20, verbosityLevel = 'normal', } = options;
159
+ // Adjust based on verbosity
160
+ const effectiveMaxFiles = this.getEffectiveMaxFiles(maxFiles, verbosityLevel);
161
+ if (this.accesses.size === 0) {
162
+ return '';
163
+ }
164
+ const allAccesses = this.getAccesses();
165
+ // Apply limit
166
+ const limitedAccesses = allAccesses.slice(0, effectiveMaxFiles);
167
+ const hasMore = allAccesses.length > effectiveMaxFiles;
168
+ // Use compact format for tight context
169
+ if (verbosityLevel === 'minimal' || verbosityLevel === 'abbreviated') {
170
+ return this.formatCompact(limitedAccesses, hasMore);
171
+ }
172
+ // Full format with grouping
173
+ if (groupByType) {
174
+ return this.formatGrouped(limitedAccesses, hasMore, {
175
+ includeLineCount,
176
+ includeSummary,
177
+ includeTimestamp,
178
+ });
179
+ }
180
+ // Flat format (not grouped)
181
+ return this.formatFlat(limitedAccesses, hasMore, {
182
+ includeLineCount,
183
+ includeSummary,
184
+ includeTimestamp,
185
+ });
186
+ }
187
+ // ==========================================================================
188
+ // Lifecycle Methods
189
+ // ==========================================================================
190
+ /**
191
+ * Clear all tracked accesses
192
+ */
193
+ clear() {
194
+ this.accesses.clear();
195
+ }
196
+ /**
197
+ * Get the number of tracked files
198
+ */
199
+ get size() {
200
+ return this.accesses.size;
201
+ }
202
+ // ==========================================================================
203
+ // Private Helpers
204
+ // ==========================================================================
205
+ normalizePath(filePath) {
206
+ // Resolve to absolute path
207
+ return path.resolve(filePath);
208
+ }
209
+ enforceMaxEntries() {
210
+ if (this.accesses.size <= this.maxEntries) {
211
+ return;
212
+ }
213
+ // Evict oldest references first, then oldest reads
214
+ const sorted = this.getAccesses().reverse(); // Oldest first
215
+ // Separate by type for eviction priority
216
+ const references = sorted.filter((a) => a.type === 'referenced');
217
+ const reads = sorted.filter((a) => a.type === 'read');
218
+ const modified = sorted.filter((a) => a.type === 'modified');
219
+ // Build eviction order: references first, then reads, modified last
220
+ const evictionOrder = [...references, ...reads, ...modified];
221
+ // Evict until under limit
222
+ while (this.accesses.size > this.maxEntries && evictionOrder.length > 0) {
223
+ const toEvict = evictionOrder.shift();
224
+ if (toEvict) {
225
+ this.accesses.delete(toEvict.path);
226
+ }
227
+ }
228
+ }
229
+ getEffectiveMaxFiles(maxFiles, verbosityLevel) {
230
+ switch (verbosityLevel) {
231
+ case 'minimal':
232
+ return Math.min(maxFiles, 3);
233
+ case 'abbreviated':
234
+ return Math.min(maxFiles, 5);
235
+ case 'normal':
236
+ return Math.min(maxFiles, 10);
237
+ case 'full':
238
+ default:
239
+ return maxFiles;
240
+ }
241
+ }
242
+ formatCompact(accesses, hasMore) {
243
+ const byType = this.groupByType(accesses);
244
+ const parts = [];
245
+ if (byType.read.length > 0) {
246
+ const names = byType.read.map((a) => this.getDisplayName(a.path)).join(', ');
247
+ parts.push(`${names} (read)`);
248
+ }
249
+ if (byType.modified.length > 0) {
250
+ const names = byType.modified.map((a) => this.getDisplayName(a.path)).join(', ');
251
+ parts.push(`${names} (modified)`);
252
+ }
253
+ if (byType.referenced.length > 0) {
254
+ const count = byType.referenced.length;
255
+ if (count <= 2) {
256
+ const names = byType.referenced.map((a) => this.getDisplayName(a.path)).join(', ');
257
+ parts.push(`${names} (referenced)`);
258
+ }
259
+ else {
260
+ const first = this.getDisplayName(byType.referenced[0].path);
261
+ parts.push(`${first} +${String(count - 1)} more (referenced)`);
262
+ }
263
+ }
264
+ const moreNote = hasMore ? ' +more' : '';
265
+ return `[Previously accessed: ${parts.join('; ')}${moreNote}]`;
266
+ }
267
+ formatGrouped(accesses, hasMore, opts) {
268
+ const byType = this.groupByType(accesses);
269
+ const lines = ['[Context compacted. Previously accessed files:]', ''];
270
+ if (byType.read.length > 0) {
271
+ const count = byType.read.length;
272
+ lines.push(`Read (${String(count)} file${count > 1 ? 's' : ''}):`);
273
+ for (const access of byType.read) {
274
+ lines.push(this.formatAccessLine(access, opts));
275
+ }
276
+ lines.push('');
277
+ }
278
+ if (byType.modified.length > 0) {
279
+ const count = byType.modified.length;
280
+ lines.push(`Modified (${String(count)} file${count > 1 ? 's' : ''}):`);
281
+ for (const access of byType.modified) {
282
+ lines.push(this.formatAccessLine(access, opts));
283
+ }
284
+ lines.push('');
285
+ }
286
+ if (byType.referenced.length > 0) {
287
+ const count = byType.referenced.length;
288
+ lines.push(`Referenced (${String(count)} file${count > 1 ? 's' : ''}):`);
289
+ for (const access of byType.referenced) {
290
+ lines.push(this.formatAccessLine(access, opts));
291
+ }
292
+ lines.push('');
293
+ }
294
+ if (hasMore) {
295
+ lines.push('(Additional files truncated)');
296
+ lines.push('');
297
+ }
298
+ lines.push('[Use read_file to re-access content if needed.]');
299
+ return lines.join('\n');
300
+ }
301
+ formatFlat(accesses, hasMore, opts) {
302
+ const lines = ['[Context compacted. Previously accessed files:]', ''];
303
+ for (const access of accesses) {
304
+ const typeLabel = access.type === 'read' ? 'R' : access.type === 'modified' ? 'M' : 'ref';
305
+ lines.push(` [${typeLabel}] ${this.formatAccessLine(access, opts).trim()}`);
306
+ }
307
+ if (hasMore) {
308
+ lines.push('');
309
+ lines.push('(Additional files truncated)');
310
+ }
311
+ lines.push('');
312
+ lines.push('[Use read_file to re-access content if needed.]');
313
+ return lines.join('\n');
314
+ }
315
+ formatAccessLine(access, opts) {
316
+ const parts = [` • ${this.getDisplayPath(access.path)}`];
317
+ if (opts.includeLineCount && access.lineCount !== undefined) {
318
+ parts.push(`(${String(access.lineCount)} lines)`);
319
+ }
320
+ if (opts.includeSummary && access.summary) {
321
+ parts.push(`- ${access.summary}`);
322
+ }
323
+ if (opts.includeTimestamp) {
324
+ const date = new Date(access.timestamp);
325
+ parts.push(`@ ${date.toISOString().slice(11, 19)}`);
326
+ }
327
+ return parts.join(' ');
328
+ }
329
+ groupByType(accesses) {
330
+ const result = {
331
+ read: [],
332
+ referenced: [],
333
+ modified: [],
334
+ };
335
+ for (const access of accesses) {
336
+ result[access.type].push(access);
337
+ }
338
+ return result;
339
+ }
340
+ getDisplayName(filePath) {
341
+ return path.basename(filePath);
342
+ }
343
+ getDisplayPath(filePath) {
344
+ // Try to make path shorter for display
345
+ const cwd = process.cwd();
346
+ if (filePath.startsWith(cwd)) {
347
+ return filePath.slice(cwd.length + 1); // Remove cwd + leading slash
348
+ }
349
+ // Truncate long absolute paths
350
+ if (filePath.length > 60) {
351
+ const parts = filePath.split(path.sep);
352
+ if (parts.length > 4) {
353
+ return `...${path.sep}${parts.slice(-3).join(path.sep)}`;
354
+ }
355
+ }
356
+ return filePath;
357
+ }
358
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * File Tracking Hook
3
+ *
4
+ * An afterTool hook that automatically tracks file accesses based on tool calls.
5
+ * This approach is cleaner than modifying each tool directly.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * const tracker = new FileAccessTracker();
10
+ * const agent = new Agent({
11
+ * hooks: {
12
+ * afterTool: [createFileTrackingHook(tracker)]
13
+ * }
14
+ * });
15
+ * ```
16
+ */
17
+ import type { AfterToolHook } from '../hooks/types.js';
18
+ import type { FileAccessTracker } from './file-tracker.js';
19
+ /**
20
+ * Create an afterTool hook that tracks file accesses
21
+ *
22
+ * @param tracker - FileAccessTracker instance to record accesses
23
+ * @returns An afterTool hook function
24
+ */
25
+ export declare function createFileTrackingHook(tracker: FileAccessTracker): AfterToolHook;
26
+ /**
27
+ * Tool names that this hook tracks
28
+ */
29
+ export declare const TRACKED_TOOLS: readonly ["read_file", "write_file", "edit", "grep", "glob"];
@@ -0,0 +1,103 @@
1
+ /**
2
+ * File Tracking Hook
3
+ *
4
+ * An afterTool hook that automatically tracks file accesses based on tool calls.
5
+ * This approach is cleaner than modifying each tool directly.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * const tracker = new FileAccessTracker();
10
+ * const agent = new Agent({
11
+ * hooks: {
12
+ * afterTool: [createFileTrackingHook(tracker)]
13
+ * }
14
+ * });
15
+ * ```
16
+ */
17
+ import { TOOL_NAMES } from '../tools/builtin/tool-names.js';
18
+ /**
19
+ * Create an afterTool hook that tracks file accesses
20
+ *
21
+ * @param tracker - FileAccessTracker instance to record accesses
22
+ * @returns An afterTool hook function
23
+ */
24
+ export function createFileTrackingHook(tracker) {
25
+ return (context) => {
26
+ const { toolName, input, result } = context;
27
+ // Only track successful operations
28
+ if (!result.success) {
29
+ return undefined;
30
+ }
31
+ switch (toolName) {
32
+ case TOOL_NAMES.READ_FILE: {
33
+ const readInput = input;
34
+ const readResult = result;
35
+ const lineCount = readResult.result?.lineCount ?? 0;
36
+ tracker.trackRead(readInput.file_path, lineCount);
37
+ break;
38
+ }
39
+ case TOOL_NAMES.WRITE_FILE: {
40
+ const writeInput = input;
41
+ tracker.trackModification(writeInput.file_path, 'File written');
42
+ break;
43
+ }
44
+ case TOOL_NAMES.EDIT: {
45
+ const editInput = input;
46
+ tracker.trackModification(editInput.file_path, 'File edited');
47
+ break;
48
+ }
49
+ case TOOL_NAMES.GREP: {
50
+ const grepInput = input;
51
+ const grepResult = result;
52
+ // Track the search path if specified
53
+ if (grepInput.path) {
54
+ tracker.trackReference(grepInput.path);
55
+ }
56
+ // Track all files that matched
57
+ if (grepResult.result?.matches) {
58
+ const seenFiles = new Set();
59
+ for (const match of grepResult.result.matches) {
60
+ if (!seenFiles.has(match.file)) {
61
+ seenFiles.add(match.file);
62
+ tracker.trackReference(match.file);
63
+ }
64
+ }
65
+ }
66
+ if (grepResult.result?.files) {
67
+ for (const file of grepResult.result.files) {
68
+ tracker.trackReference(file);
69
+ }
70
+ }
71
+ break;
72
+ }
73
+ case TOOL_NAMES.GLOB: {
74
+ const globInput = input;
75
+ const globResult = result;
76
+ // Track the search path if specified
77
+ if (globInput.path) {
78
+ tracker.trackReference(globInput.path);
79
+ }
80
+ // Track all matched files
81
+ if (globResult.result?.files) {
82
+ for (const file of globResult.result.files) {
83
+ tracker.trackReference(file);
84
+ }
85
+ }
86
+ break;
87
+ }
88
+ // Note: bash tool could potentially be tracked for file operations,
89
+ // but it's complex to parse shell commands. Skip for now.
90
+ }
91
+ return undefined;
92
+ };
93
+ }
94
+ /**
95
+ * Tool names that this hook tracks
96
+ */
97
+ export const TRACKED_TOOLS = [
98
+ TOOL_NAMES.READ_FILE,
99
+ TOOL_NAMES.WRITE_FILE,
100
+ TOOL_NAMES.EDIT,
101
+ TOOL_NAMES.GREP,
102
+ TOOL_NAMES.GLOB,
103
+ ];
@@ -6,7 +6,11 @@
6
6
  * - Filtering (truncate large content)
7
7
  * - Compaction (save to files, replace with references)
8
8
  * - Summarization (compress history when near limit)
9
+ * - File access tracking (for context restoration hints)
9
10
  */
10
11
  export { ContextManager, DEFAULT_CONTEXT_CONFIG } from './manager.js';
11
12
  export type { ContextManagerOptions } from './manager.js';
12
- export type { ContextCategory, BudgetAllocation, CategoryBudgetInfo, PreflightResult, VerbosityLevel, VerbosityConfig, ContextConfig, FilteringConfig, CompactionConfig, SummarizationConfig, CompactionResult, SummarizationResult, FilteringResult, ContextEvent, ContextEventHandler, ContextStats, } from './types.js';
13
+ export { FileAccessTracker } from './file-tracker.js';
14
+ export type { FileAccessType, FileAccess, FileAccessTrackerOptions, FormatHintsOptions, FileAccessStats, } from './file-tracker.js';
15
+ export { createFileTrackingHook, TRACKED_TOOLS } from './file-tracking-hook.js';
16
+ export type { ContextCategory, BudgetAllocation, CategoryBudgetInfo, PreflightResult, VerbosityLevel, VerbosityConfig, ContextConfig, FilteringConfig, CompactionConfig, SummarizationConfig, CompactionResult, SummarizationResult, FilteringResult, ContextEvent, ContextEventHandler, ContextStats, CategorizedMessages, SmartCompactOptions, SmartCompactionResult, } from './types.js';
@@ -6,5 +6,8 @@
6
6
  * - Filtering (truncate large content)
7
7
  * - Compaction (save to files, replace with references)
8
8
  * - Summarization (compress history when near limit)
9
+ * - File access tracking (for context restoration hints)
9
10
  */
10
11
  export { ContextManager, DEFAULT_CONTEXT_CONFIG } from './manager.js';
12
+ export { FileAccessTracker } from './file-tracker.js';
13
+ export { createFileTrackingHook, TRACKED_TOOLS } from './file-tracking-hook.js';