dino-spec 13.6.0 → 14.0.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.
Files changed (88) hide show
  1. package/bin/dino-hud.js +1 -1
  2. package/bin/dino.js +1 -1
  3. package/dist/core/agents/context-isolation.js +26 -26
  4. package/dist/core/context/__tests__/budget-thresholds.test.d.ts +5 -0
  5. package/dist/core/context/__tests__/budget-thresholds.test.d.ts.map +1 -0
  6. package/dist/core/context/__tests__/budget-thresholds.test.js +223 -0
  7. package/dist/core/context/__tests__/budget-thresholds.test.js.map +1 -0
  8. package/dist/core/context/__tests__/compaction-engine.test.d.ts +5 -0
  9. package/dist/core/context/__tests__/compaction-engine.test.d.ts.map +1 -0
  10. package/dist/core/context/__tests__/compaction-engine.test.js +474 -0
  11. package/dist/core/context/__tests__/compaction-engine.test.js.map +1 -0
  12. package/dist/core/context/__tests__/output-persistence.test.d.ts +5 -0
  13. package/dist/core/context/__tests__/output-persistence.test.d.ts.map +1 -0
  14. package/dist/core/context/__tests__/output-persistence.test.js +246 -0
  15. package/dist/core/context/__tests__/output-persistence.test.js.map +1 -0
  16. package/dist/core/context/budget-thresholds.d.ts +167 -0
  17. package/dist/core/context/budget-thresholds.d.ts.map +1 -0
  18. package/dist/core/context/budget-thresholds.js +234 -0
  19. package/dist/core/context/budget-thresholds.js.map +1 -0
  20. package/dist/core/context/compaction-engine.d.ts +193 -0
  21. package/dist/core/context/compaction-engine.d.ts.map +1 -0
  22. package/dist/core/context/compaction-engine.js +376 -0
  23. package/dist/core/context/compaction-engine.js.map +1 -0
  24. package/dist/core/context/index.d.ts +7 -3
  25. package/dist/core/context/index.d.ts.map +1 -1
  26. package/dist/core/context/index.js +22 -3
  27. package/dist/core/context/index.js.map +1 -1
  28. package/dist/core/context/output-persistence.d.ts +142 -0
  29. package/dist/core/context/output-persistence.d.ts.map +1 -0
  30. package/dist/core/context/output-persistence.js +242 -0
  31. package/dist/core/context/output-persistence.js.map +1 -0
  32. package/dist/core/environment/__tests__/pre-verify.test.d.ts +5 -0
  33. package/dist/core/environment/__tests__/pre-verify.test.d.ts.map +1 -0
  34. package/dist/core/environment/__tests__/pre-verify.test.js +343 -0
  35. package/dist/core/environment/__tests__/pre-verify.test.js.map +1 -0
  36. package/dist/core/environment/index.d.ts +8 -0
  37. package/dist/core/environment/index.d.ts.map +1 -0
  38. package/dist/core/environment/index.js +7 -0
  39. package/dist/core/environment/index.js.map +1 -0
  40. package/dist/core/environment/pre-verify.d.ts +63 -0
  41. package/dist/core/environment/pre-verify.d.ts.map +1 -0
  42. package/dist/core/environment/pre-verify.js +221 -0
  43. package/dist/core/environment/pre-verify.js.map +1 -0
  44. package/dist/core/environment/types.d.ts +37 -0
  45. package/dist/core/environment/types.d.ts.map +1 -0
  46. package/dist/core/environment/types.js +5 -0
  47. package/dist/core/environment/types.js.map +1 -0
  48. package/dist/core/intelligence/context-budget.d.ts +10 -5
  49. package/dist/core/intelligence/context-budget.d.ts.map +1 -1
  50. package/dist/core/intelligence/context-budget.js +12 -5
  51. package/dist/core/intelligence/context-budget.js.map +1 -1
  52. package/dist/mcp/__tests__/dynamic-updates.test.d.ts +5 -0
  53. package/dist/mcp/__tests__/dynamic-updates.test.d.ts.map +1 -0
  54. package/dist/mcp/__tests__/dynamic-updates.test.js +314 -0
  55. package/dist/mcp/__tests__/dynamic-updates.test.js.map +1 -0
  56. package/dist/mcp/dynamic-updates.d.ts +167 -0
  57. package/dist/mcp/dynamic-updates.d.ts.map +1 -0
  58. package/dist/mcp/dynamic-updates.js +313 -0
  59. package/dist/mcp/dynamic-updates.js.map +1 -0
  60. package/dist/mcp/index.d.ts +4 -2
  61. package/dist/mcp/index.d.ts.map +1 -1
  62. package/dist/mcp/index.js +5 -2
  63. package/dist/mcp/index.js.map +1 -1
  64. package/dist/mcp/registry.d.ts +4 -4
  65. package/dist/mcp/registry.d.ts.map +1 -1
  66. package/dist/mcp/registry.js +16 -16
  67. package/dist/mcp/registry.js.map +1 -1
  68. package/dist/mcp/tools/__tests__/environment.test.d.ts +5 -0
  69. package/dist/mcp/tools/__tests__/environment.test.d.ts.map +1 -0
  70. package/dist/mcp/tools/__tests__/environment.test.js +219 -0
  71. package/dist/mcp/tools/__tests__/environment.test.js.map +1 -0
  72. package/dist/mcp/tools/environment.d.ts +27 -0
  73. package/dist/mcp/tools/environment.d.ts.map +1 -0
  74. package/dist/mcp/tools/environment.js +97 -0
  75. package/dist/mcp/tools/environment.js.map +1 -0
  76. package/dist/mcp/tools/index.d.ts +3 -1
  77. package/dist/mcp/tools/index.d.ts.map +1 -1
  78. package/dist/mcp/tools/index.js +13 -1
  79. package/dist/mcp/tools/index.js.map +1 -1
  80. package/dist/mcp/tools/output-persistence.d.ts +44 -0
  81. package/dist/mcp/tools/output-persistence.d.ts.map +1 -0
  82. package/dist/mcp/tools/output-persistence.js +208 -0
  83. package/dist/mcp/tools/output-persistence.js.map +1 -0
  84. package/dist/mcp-server.d.ts +2 -1
  85. package/dist/mcp-server.d.ts.map +1 -1
  86. package/dist/mcp-server.js +27 -2
  87. package/dist/mcp-server.js.map +1 -1
  88. package/package.json +1 -1
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Output Persistence Tests - v14.0.0
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
+ import { join } from 'path';
6
+ import { mkdir, rm, writeFile } from 'fs/promises';
7
+ import { OUTPUT_SIZE_THRESHOLD, OUTPUT_DIR, OUTPUT_RETENTION_DAYS, shouldPersist, persistOutput, readPersistedOutput, listPersistedOutputs, cleanupExpiredOutputs, getPersistedOutputsStats, generateContentHash, generateOutputFilename, createFileReference, parseFileReference, formatPersistenceResult, } from '../output-persistence.js';
8
+ describe('Output Persistence', () => {
9
+ const testDir = join(process.cwd(), 'test-output-persistence-temp');
10
+ beforeEach(async () => {
11
+ // Create fresh test directory
12
+ await mkdir(testDir, { recursive: true });
13
+ });
14
+ afterEach(async () => {
15
+ // Clean up test directory
16
+ try {
17
+ await rm(testDir, { recursive: true, force: true });
18
+ }
19
+ catch {
20
+ // Ignore errors
21
+ }
22
+ });
23
+ describe('Constants', () => {
24
+ it('should have correct size threshold', () => {
25
+ expect(OUTPUT_SIZE_THRESHOLD).toBe(30_000);
26
+ });
27
+ it('should have correct output directory', () => {
28
+ expect(OUTPUT_DIR).toBe('.dino/outputs');
29
+ });
30
+ it('should have correct retention days', () => {
31
+ expect(OUTPUT_RETENTION_DAYS).toBe(7);
32
+ });
33
+ });
34
+ describe('generateContentHash', () => {
35
+ it('should generate 8-character hash', () => {
36
+ const hash = generateContentHash('test content');
37
+ expect(hash.length).toBe(8);
38
+ });
39
+ it('should generate consistent hash for same content', () => {
40
+ const hash1 = generateContentHash('test content');
41
+ const hash2 = generateContentHash('test content');
42
+ expect(hash1).toBe(hash2);
43
+ });
44
+ it('should generate different hash for different content', () => {
45
+ const hash1 = generateContentHash('content 1');
46
+ const hash2 = generateContentHash('content 2');
47
+ expect(hash1).not.toBe(hash2);
48
+ });
49
+ });
50
+ describe('generateOutputFilename', () => {
51
+ it('should generate filename with timestamp and hash', () => {
52
+ const filename = generateOutputFilename('test content');
53
+ expect(filename).toMatch(/^\d{4}-\d{2}-\d{2}T.*-[a-f0-9]{8}\.txt$/);
54
+ });
55
+ it('should generate unique filenames', () => {
56
+ const filename1 = generateOutputFilename('content 1');
57
+ const filename2 = generateOutputFilename('content 2');
58
+ expect(filename1).not.toBe(filename2);
59
+ });
60
+ });
61
+ describe('shouldPersist', () => {
62
+ it('should return false for small content', () => {
63
+ const smallContent = 'a'.repeat(1000);
64
+ expect(shouldPersist(smallContent)).toBe(false);
65
+ });
66
+ it('should return true for large content', () => {
67
+ const largeContent = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 1);
68
+ expect(shouldPersist(largeContent)).toBe(true);
69
+ });
70
+ it('should return false for content exactly at threshold', () => {
71
+ const exactContent = 'a'.repeat(OUTPUT_SIZE_THRESHOLD);
72
+ expect(shouldPersist(exactContent)).toBe(false);
73
+ });
74
+ it('should respect custom threshold', () => {
75
+ const content = 'a'.repeat(500);
76
+ expect(shouldPersist(content, { threshold: 100 })).toBe(true);
77
+ });
78
+ it('should persist when forced', () => {
79
+ const smallContent = 'a'.repeat(100);
80
+ expect(shouldPersist(smallContent, { force: true })).toBe(true);
81
+ });
82
+ });
83
+ describe('createFileReference', () => {
84
+ it('should create properly formatted reference', () => {
85
+ const ref = createFileReference('.dino/outputs/test.txt', 50000);
86
+ expect(ref).toContain('[Output persisted to:');
87
+ expect(ref).toContain('.dino/outputs/test.txt');
88
+ expect(ref).toContain('50,000 chars');
89
+ expect(ref).toContain('tokens');
90
+ });
91
+ });
92
+ describe('parseFileReference', () => {
93
+ it('should parse valid file reference', () => {
94
+ const ref = '[Output persisted to: .dino/outputs/test.txt (50,000 chars, ~12,500 tokens)]';
95
+ expect(parseFileReference(ref)).toBe('.dino/outputs/test.txt');
96
+ });
97
+ it('should return null for invalid reference', () => {
98
+ expect(parseFileReference('not a reference')).toBeNull();
99
+ });
100
+ it('should return null for empty string', () => {
101
+ expect(parseFileReference('')).toBeNull();
102
+ });
103
+ });
104
+ describe('persistOutput', () => {
105
+ it('should not persist small content', async () => {
106
+ const smallContent = 'small content';
107
+ const result = await persistOutput(smallContent, testDir);
108
+ expect(result.persisted).toBe(false);
109
+ expect(result.reference).toBe(smallContent);
110
+ expect(result.tokensSaved).toBe(0);
111
+ });
112
+ it('should persist large content', async () => {
113
+ const largeContent = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 1000);
114
+ const result = await persistOutput(largeContent, testDir);
115
+ expect(result.persisted).toBe(true);
116
+ expect(result.reference).toContain('[Output persisted to:');
117
+ expect(result.originalSize).toBe(largeContent.length);
118
+ expect(result.tokensSaved).toBeGreaterThan(0);
119
+ });
120
+ it('should create output file', async () => {
121
+ const largeContent = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 1000);
122
+ const result = await persistOutput(largeContent, testDir);
123
+ // Extract path from reference
124
+ const path = parseFileReference(result.reference);
125
+ expect(path).not.toBeNull();
126
+ // Verify file exists
127
+ const content = await readPersistedOutput(path, testDir);
128
+ expect(content).toBe(largeContent);
129
+ });
130
+ it('should create metadata file', async () => {
131
+ const largeContent = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 1000);
132
+ await persistOutput(largeContent, testDir, { source: 'test-tool' });
133
+ const outputs = await listPersistedOutputs(testDir);
134
+ expect(outputs.length).toBe(1);
135
+ expect(outputs[0].source).toBe('test-tool');
136
+ expect(outputs[0].sizeChars).toBe(largeContent.length);
137
+ });
138
+ });
139
+ describe('readPersistedOutput', () => {
140
+ it('should read existing output', async () => {
141
+ const content = 'test content for reading';
142
+ const outputDir = join(testDir, OUTPUT_DIR);
143
+ await mkdir(outputDir, { recursive: true });
144
+ const filePath = join(outputDir, 'test-read.txt');
145
+ await writeFile(filePath, content);
146
+ const result = await readPersistedOutput(join(OUTPUT_DIR, 'test-read.txt'), testDir);
147
+ expect(result).toBe(content);
148
+ });
149
+ it('should return null for non-existent file', async () => {
150
+ const result = await readPersistedOutput('.dino/outputs/nonexistent.txt', testDir);
151
+ expect(result).toBeNull();
152
+ });
153
+ });
154
+ describe('listPersistedOutputs', () => {
155
+ it('should return empty array when no outputs', async () => {
156
+ const outputs = await listPersistedOutputs(testDir);
157
+ expect(outputs).toEqual([]);
158
+ });
159
+ it('should list all outputs', async () => {
160
+ // Create multiple outputs
161
+ const content1 = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 100);
162
+ const content2 = 'b'.repeat(OUTPUT_SIZE_THRESHOLD + 200);
163
+ await persistOutput(content1, testDir, { source: 'tool1' });
164
+ await persistOutput(content2, testDir, { source: 'tool2' });
165
+ const outputs = await listPersistedOutputs(testDir);
166
+ expect(outputs.length).toBe(2);
167
+ });
168
+ });
169
+ describe('cleanupExpiredOutputs', () => {
170
+ it('should clean up expired outputs', async () => {
171
+ // Create an expired output manually
172
+ const outputDir = join(testDir, OUTPUT_DIR);
173
+ await mkdir(outputDir, { recursive: true });
174
+ const expiredMeta = {
175
+ path: join(OUTPUT_DIR, 'expired.txt'),
176
+ hash: 'abc12345',
177
+ sizeChars: 1000,
178
+ createdAt: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString(), // 10 days ago
179
+ expiresAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(), // 3 days ago (expired)
180
+ };
181
+ await writeFile(join(outputDir, 'expired.txt'), 'expired content');
182
+ await writeFile(join(outputDir, 'expired.meta.json'), JSON.stringify(expiredMeta));
183
+ const cleaned = await cleanupExpiredOutputs(testDir);
184
+ expect(cleaned).toBe(1);
185
+ // Verify file is gone
186
+ const outputs = await listPersistedOutputs(testDir);
187
+ expect(outputs.length).toBe(0);
188
+ });
189
+ it('should not clean up non-expired outputs', async () => {
190
+ const content = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 100);
191
+ await persistOutput(content, testDir);
192
+ const cleaned = await cleanupExpiredOutputs(testDir);
193
+ expect(cleaned).toBe(0);
194
+ const outputs = await listPersistedOutputs(testDir);
195
+ expect(outputs.length).toBe(1);
196
+ });
197
+ });
198
+ describe('getPersistedOutputsStats', () => {
199
+ it('should return empty stats when no outputs', async () => {
200
+ const stats = await getPersistedOutputsStats(testDir);
201
+ expect(stats.count).toBe(0);
202
+ expect(stats.totalChars).toBe(0);
203
+ expect(stats.estimatedTokensSaved).toBe(0);
204
+ });
205
+ it('should calculate correct stats', async () => {
206
+ const content1 = 'a'.repeat(OUTPUT_SIZE_THRESHOLD + 100);
207
+ const content2 = 'b'.repeat(OUTPUT_SIZE_THRESHOLD + 200);
208
+ await persistOutput(content1, testDir);
209
+ await persistOutput(content2, testDir);
210
+ const stats = await getPersistedOutputsStats(testDir);
211
+ expect(stats.count).toBe(2);
212
+ expect(stats.totalChars).toBe(content1.length + content2.length);
213
+ expect(stats.estimatedTokensSaved).toBeGreaterThan(0);
214
+ expect(stats.oldestOutput).not.toBeNull();
215
+ expect(stats.newestOutput).not.toBeNull();
216
+ });
217
+ });
218
+ describe('formatPersistenceResult', () => {
219
+ it('should format non-persisted result', () => {
220
+ const result = {
221
+ persisted: false,
222
+ reference: 'original content',
223
+ originalSize: 15,
224
+ estimatedTokens: 4,
225
+ tokensSaved: 0,
226
+ };
227
+ const formatted = formatPersistenceResult(result);
228
+ expect(formatted).toContain('not persisted');
229
+ expect(formatted).toContain('below threshold');
230
+ });
231
+ it('should format persisted result', () => {
232
+ const result = {
233
+ persisted: true,
234
+ reference: '[Output persisted to: .dino/outputs/test.txt (50,000 chars, ~12,500 tokens)]',
235
+ originalSize: 50000,
236
+ estimatedTokens: 12500,
237
+ tokensSaved: 12450,
238
+ };
239
+ const formatted = formatPersistenceResult(result);
240
+ expect(formatted).toContain('successfully');
241
+ expect(formatted).toContain('50,000 chars');
242
+ expect(formatted).toContain('Tokens saved');
243
+ });
244
+ });
245
+ });
246
+ //# sourceMappingURL=output-persistence.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-persistence.test.js","sourceRoot":"","sources":["../../../../src/core/context/__tests__/output-persistence.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Budget Thresholds - v14.0.0
3
+ *
4
+ * Configurable context budget thresholds with safety margins.
5
+ * Optimized for Claude 4.5's extended context window (200K tokens).
6
+ *
7
+ * Key improvements over v13.x:
8
+ * - Raised thresholds from 80/90/95% to 85/95/98%
9
+ * - Safety margin calculation for reliable headroom
10
+ * - Config-driven thresholds via .dino/config.json
11
+ * - Backwards compatible with existing budget tracking
12
+ *
13
+ * Reference: Anthropic context engineering best practices
14
+ */
15
+ /**
16
+ * Default budget thresholds (v14.0.0)
17
+ *
18
+ * These thresholds are optimized for safe context utilization
19
+ * while maximizing available token budget.
20
+ */
21
+ export declare const OPTIMIZED_BUDGET_THRESHOLDS: {
22
+ /** Start monitoring - context filling up */
23
+ readonly WARNING: 0.85;
24
+ /** High usage - recommend compaction */
25
+ readonly HIGH: 0.95;
26
+ /** Critical - force compaction recommendation */
27
+ readonly CRITICAL: 0.98;
28
+ };
29
+ /**
30
+ * Legacy thresholds for backwards compatibility
31
+ */
32
+ export declare const LEGACY_BUDGET_THRESHOLDS: {
33
+ readonly WARNING: 0.8;
34
+ readonly HIGH: 0.9;
35
+ readonly CRITICAL: 0.95;
36
+ };
37
+ /**
38
+ * Default safety margin in tokens
39
+ *
40
+ * Reserved buffer to prevent context overflow.
41
+ * Provides headroom for system messages and unexpected content.
42
+ */
43
+ export declare const DEFAULT_SAFETY_MARGIN = 2000;
44
+ /**
45
+ * Threshold configuration interface
46
+ */
47
+ export interface ThresholdConfig {
48
+ /** Warning threshold (0-1) */
49
+ warning: number;
50
+ /** High threshold (0-1) */
51
+ high: number;
52
+ /** Critical threshold (0-1) */
53
+ critical: number;
54
+ /** Safety margin in tokens */
55
+ safetyMargin: number;
56
+ }
57
+ /**
58
+ * Threshold level type
59
+ */
60
+ export type ThresholdLevel = 'safe' | 'warning' | 'high' | 'critical';
61
+ /**
62
+ * Threshold result with remaining capacity
63
+ */
64
+ export interface ThresholdResult {
65
+ /** Current threshold level */
66
+ level: ThresholdLevel;
67
+ /** Remaining tokens before limit */
68
+ remaining: number;
69
+ /** Safe remaining after subtracting safety margin */
70
+ safeRemaining: number;
71
+ /** Current usage percentage (0-100) */
72
+ percentage: number;
73
+ /** Whether compaction is recommended */
74
+ shouldCompact: boolean;
75
+ /** Whether compaction is urgent */
76
+ forceCompact: boolean;
77
+ }
78
+ /**
79
+ * Default threshold configuration
80
+ */
81
+ export declare const DEFAULT_THRESHOLD_CONFIG: ThresholdConfig;
82
+ /**
83
+ * Get threshold level from usage percentage
84
+ *
85
+ * @param usage - Current token usage
86
+ * @param limit - Context limit in tokens
87
+ * @param config - Threshold configuration (optional)
88
+ * @returns ThresholdLevel
89
+ */
90
+ export declare function getThresholdLevel(usage: number, limit: number, config?: ThresholdConfig): ThresholdLevel;
91
+ /**
92
+ * Calculate threshold result with safety margin
93
+ *
94
+ * @param usage - Current token usage
95
+ * @param limit - Context limit in tokens
96
+ * @param config - Threshold configuration (optional)
97
+ * @returns ThresholdResult with remaining capacity
98
+ */
99
+ export declare function calculateThresholdResult(usage: number, limit: number, config?: ThresholdConfig): ThresholdResult;
100
+ /**
101
+ * Load threshold configuration from config.json
102
+ *
103
+ * Configuration can be customized via .dino/config.json:
104
+ * ```json
105
+ * {
106
+ * "custom": {
107
+ * "budgetThresholds": {
108
+ * "warning": 0.85,
109
+ * "high": 0.95,
110
+ * "critical": 0.98,
111
+ * "safetyMargin": 2000
112
+ * }
113
+ * }
114
+ * }
115
+ * ```
116
+ *
117
+ * Falls back to optimized thresholds if not configured.
118
+ *
119
+ * @param projectDir - Project directory
120
+ * @returns ThresholdConfig
121
+ */
122
+ export declare function loadThresholdConfig(projectDir?: string): Promise<ThresholdConfig>;
123
+ /**
124
+ * Check if using legacy thresholds
125
+ *
126
+ * Returns true if config has legacy threshold values.
127
+ * Useful for migration warnings.
128
+ *
129
+ * @param config - Threshold configuration
130
+ * @returns boolean
131
+ */
132
+ export declare function isLegacyThresholds(config: ThresholdConfig): boolean;
133
+ /**
134
+ * Get recommendations for threshold level
135
+ *
136
+ * @param level - Current threshold level
137
+ * @returns Array of recommended actions
138
+ */
139
+ export declare function getThresholdRecommendations(level: ThresholdLevel): string[];
140
+ /**
141
+ * Format threshold result for display
142
+ *
143
+ * @param result - Threshold result
144
+ * @returns Formatted string
145
+ */
146
+ export declare function formatThresholdResult(result: ThresholdResult): string;
147
+ /**
148
+ * Calculate safe capacity at a threshold
149
+ *
150
+ * Returns the amount of tokens that can be safely used
151
+ * before hitting the specified threshold.
152
+ *
153
+ * @param limit - Context limit in tokens
154
+ * @param threshold - Threshold percentage (0-1)
155
+ * @param safetyMargin - Safety margin in tokens
156
+ * @returns Safe capacity in tokens
157
+ */
158
+ export declare function calculateSafeCapacity(limit: number, threshold: number, safetyMargin?: number): number;
159
+ /**
160
+ * Get effective limit accounting for safety margin
161
+ *
162
+ * @param limit - Context limit in tokens
163
+ * @param config - Threshold configuration
164
+ * @returns Effective limit with safety margin applied
165
+ */
166
+ export declare function getEffectiveLimit(limit: number, config?: ThresholdConfig): number;
167
+ //# sourceMappingURL=budget-thresholds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-thresholds.d.ts","sourceRoot":"","sources":["../../../src/core/context/budget-thresholds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;IACtC,4CAA4C;;IAE5C,wCAAwC;;IAExC,iDAAiD;;CAEzC,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;CAI3B,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,aAAa,EAAE,OAAO,CAAC;IACvB,mCAAmC;IACnC,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAKtC,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,eAA0C,GACjD,cAAc,CAahB;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,eAA0C,GACjD,eAAe,CAcjB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,GAAE,MAAsB,GACjC,OAAO,CAAC,eAAe,CAAC,CAkB1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAMnE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CA0B3E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAsBrE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,MAA8B,GAC3C,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,eAA0C,GACjD,MAAM,CAGR"}
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Budget Thresholds - v14.0.0
3
+ *
4
+ * Configurable context budget thresholds with safety margins.
5
+ * Optimized for Claude 4.5's extended context window (200K tokens).
6
+ *
7
+ * Key improvements over v13.x:
8
+ * - Raised thresholds from 80/90/95% to 85/95/98%
9
+ * - Safety margin calculation for reliable headroom
10
+ * - Config-driven thresholds via .dino/config.json
11
+ * - Backwards compatible with existing budget tracking
12
+ *
13
+ * Reference: Anthropic context engineering best practices
14
+ */
15
+ import { loadConfig } from '../config/feature-flags.js';
16
+ /**
17
+ * Default budget thresholds (v14.0.0)
18
+ *
19
+ * These thresholds are optimized for safe context utilization
20
+ * while maximizing available token budget.
21
+ */
22
+ export const OPTIMIZED_BUDGET_THRESHOLDS = {
23
+ /** Start monitoring - context filling up */
24
+ WARNING: 0.85, // was 0.80
25
+ /** High usage - recommend compaction */
26
+ HIGH: 0.95, // was 0.90
27
+ /** Critical - force compaction recommendation */
28
+ CRITICAL: 0.98, // was 0.95
29
+ };
30
+ /**
31
+ * Legacy thresholds for backwards compatibility
32
+ */
33
+ export const LEGACY_BUDGET_THRESHOLDS = {
34
+ WARNING: 0.80,
35
+ HIGH: 0.90,
36
+ CRITICAL: 0.95,
37
+ };
38
+ /**
39
+ * Default safety margin in tokens
40
+ *
41
+ * Reserved buffer to prevent context overflow.
42
+ * Provides headroom for system messages and unexpected content.
43
+ */
44
+ export const DEFAULT_SAFETY_MARGIN = 2000;
45
+ /**
46
+ * Default threshold configuration
47
+ */
48
+ export const DEFAULT_THRESHOLD_CONFIG = {
49
+ warning: OPTIMIZED_BUDGET_THRESHOLDS.WARNING,
50
+ high: OPTIMIZED_BUDGET_THRESHOLDS.HIGH,
51
+ critical: OPTIMIZED_BUDGET_THRESHOLDS.CRITICAL,
52
+ safetyMargin: DEFAULT_SAFETY_MARGIN,
53
+ };
54
+ /**
55
+ * Get threshold level from usage percentage
56
+ *
57
+ * @param usage - Current token usage
58
+ * @param limit - Context limit in tokens
59
+ * @param config - Threshold configuration (optional)
60
+ * @returns ThresholdLevel
61
+ */
62
+ export function getThresholdLevel(usage, limit, config = DEFAULT_THRESHOLD_CONFIG) {
63
+ const percentage = usage / limit;
64
+ if (percentage >= config.critical) {
65
+ return 'critical';
66
+ }
67
+ if (percentage >= config.high) {
68
+ return 'high';
69
+ }
70
+ if (percentage >= config.warning) {
71
+ return 'warning';
72
+ }
73
+ return 'safe';
74
+ }
75
+ /**
76
+ * Calculate threshold result with safety margin
77
+ *
78
+ * @param usage - Current token usage
79
+ * @param limit - Context limit in tokens
80
+ * @param config - Threshold configuration (optional)
81
+ * @returns ThresholdResult with remaining capacity
82
+ */
83
+ export function calculateThresholdResult(usage, limit, config = DEFAULT_THRESHOLD_CONFIG) {
84
+ const level = getThresholdLevel(usage, limit, config);
85
+ const remaining = Math.max(0, limit - usage);
86
+ const safeRemaining = Math.max(0, remaining - config.safetyMargin);
87
+ const percentage = Math.round((usage / limit) * 100);
88
+ return {
89
+ level,
90
+ remaining,
91
+ safeRemaining,
92
+ percentage,
93
+ shouldCompact: level === 'high' || level === 'critical',
94
+ forceCompact: level === 'critical',
95
+ };
96
+ }
97
+ /**
98
+ * Load threshold configuration from config.json
99
+ *
100
+ * Configuration can be customized via .dino/config.json:
101
+ * ```json
102
+ * {
103
+ * "custom": {
104
+ * "budgetThresholds": {
105
+ * "warning": 0.85,
106
+ * "high": 0.95,
107
+ * "critical": 0.98,
108
+ * "safetyMargin": 2000
109
+ * }
110
+ * }
111
+ * }
112
+ * ```
113
+ *
114
+ * Falls back to optimized thresholds if not configured.
115
+ *
116
+ * @param projectDir - Project directory
117
+ * @returns ThresholdConfig
118
+ */
119
+ export async function loadThresholdConfig(projectDir = process.cwd()) {
120
+ try {
121
+ const config = await loadConfig(projectDir);
122
+ const customThresholds = config.custom?.budgetThresholds;
123
+ if (customThresholds) {
124
+ return {
125
+ warning: customThresholds.warning ?? DEFAULT_THRESHOLD_CONFIG.warning,
126
+ high: customThresholds.high ?? DEFAULT_THRESHOLD_CONFIG.high,
127
+ critical: customThresholds.critical ?? DEFAULT_THRESHOLD_CONFIG.critical,
128
+ safetyMargin: customThresholds.safetyMargin ?? DEFAULT_THRESHOLD_CONFIG.safetyMargin,
129
+ };
130
+ }
131
+ }
132
+ catch {
133
+ // Fall back to defaults on any error
134
+ }
135
+ return DEFAULT_THRESHOLD_CONFIG;
136
+ }
137
+ /**
138
+ * Check if using legacy thresholds
139
+ *
140
+ * Returns true if config has legacy threshold values.
141
+ * Useful for migration warnings.
142
+ *
143
+ * @param config - Threshold configuration
144
+ * @returns boolean
145
+ */
146
+ export function isLegacyThresholds(config) {
147
+ return (config.warning === LEGACY_BUDGET_THRESHOLDS.WARNING &&
148
+ config.high === LEGACY_BUDGET_THRESHOLDS.HIGH &&
149
+ config.critical === LEGACY_BUDGET_THRESHOLDS.CRITICAL);
150
+ }
151
+ /**
152
+ * Get recommendations for threshold level
153
+ *
154
+ * @param level - Current threshold level
155
+ * @returns Array of recommended actions
156
+ */
157
+ export function getThresholdRecommendations(level) {
158
+ switch (level) {
159
+ case 'critical':
160
+ return [
161
+ 'CRITICAL: Context at 98%+. Immediate compaction required.',
162
+ 'Run: dino compact --force',
163
+ 'Or start a new conversation with /dino.handoff',
164
+ 'Consider using /dino.fossil to archive completed work.',
165
+ ];
166
+ case 'high':
167
+ return [
168
+ 'HIGH: Context at 95%+. Compaction recommended.',
169
+ 'Run: dino compact',
170
+ 'Avoid loading large files. Use targeted searches.',
171
+ 'Checkpoint progress for potential handoff.',
172
+ ];
173
+ case 'warning':
174
+ return [
175
+ 'WARNING: Context at 85%+. Monitor usage.',
176
+ 'Prefer grep/glob over full file reads.',
177
+ 'Consider deferring non-essential file reads.',
178
+ ];
179
+ case 'safe':
180
+ default:
181
+ return [];
182
+ }
183
+ }
184
+ /**
185
+ * Format threshold result for display
186
+ *
187
+ * @param result - Threshold result
188
+ * @returns Formatted string
189
+ */
190
+ export function formatThresholdResult(result) {
191
+ const indicator = result.level === 'critical' ? '[!!!]'
192
+ : result.level === 'high' ? '[!!]'
193
+ : result.level === 'warning' ? '[!]'
194
+ : '[OK]';
195
+ const lines = [];
196
+ lines.push(`## Budget Status ${indicator}`);
197
+ lines.push('');
198
+ lines.push(`**Level:** ${result.level.toUpperCase()} (${result.percentage}% used)`);
199
+ lines.push(`**Remaining:** ${Math.round(result.remaining / 1000)}K tokens`);
200
+ lines.push(`**Safe Remaining:** ${Math.round(result.safeRemaining / 1000)}K tokens`);
201
+ const recommendations = getThresholdRecommendations(result.level);
202
+ if (recommendations.length > 0) {
203
+ lines.push('');
204
+ lines.push('### Recommendations:');
205
+ recommendations.forEach((rec) => lines.push(`- ${rec}`));
206
+ }
207
+ return lines.join('\n');
208
+ }
209
+ /**
210
+ * Calculate safe capacity at a threshold
211
+ *
212
+ * Returns the amount of tokens that can be safely used
213
+ * before hitting the specified threshold.
214
+ *
215
+ * @param limit - Context limit in tokens
216
+ * @param threshold - Threshold percentage (0-1)
217
+ * @param safetyMargin - Safety margin in tokens
218
+ * @returns Safe capacity in tokens
219
+ */
220
+ export function calculateSafeCapacity(limit, threshold, safetyMargin = DEFAULT_SAFETY_MARGIN) {
221
+ return Math.max(0, Math.floor(limit * threshold) - safetyMargin);
222
+ }
223
+ /**
224
+ * Get effective limit accounting for safety margin
225
+ *
226
+ * @param limit - Context limit in tokens
227
+ * @param config - Threshold configuration
228
+ * @returns Effective limit with safety margin applied
229
+ */
230
+ export function getEffectiveLimit(limit, config = DEFAULT_THRESHOLD_CONFIG) {
231
+ // Use high threshold as the practical limit
232
+ return calculateSafeCapacity(limit, config.high, config.safetyMargin);
233
+ }
234
+ //# sourceMappingURL=budget-thresholds.js.map