@claudetools/tools 0.8.2 → 0.8.4

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 (74) hide show
  1. package/dist/cli.js +41 -0
  2. package/dist/context/deduplication.d.ts +72 -0
  3. package/dist/context/deduplication.js +77 -0
  4. package/dist/context/deduplication.test.d.ts +6 -0
  5. package/dist/context/deduplication.test.js +84 -0
  6. package/dist/context/emergency-eviction.d.ts +73 -0
  7. package/dist/context/emergency-eviction.example.d.ts +13 -0
  8. package/dist/context/emergency-eviction.example.js +94 -0
  9. package/dist/context/emergency-eviction.js +226 -0
  10. package/dist/context/eviction-engine.d.ts +76 -0
  11. package/dist/context/eviction-engine.example.d.ts +7 -0
  12. package/dist/context/eviction-engine.example.js +144 -0
  13. package/dist/context/eviction-engine.js +176 -0
  14. package/dist/context/example-usage.d.ts +1 -0
  15. package/dist/context/example-usage.js +128 -0
  16. package/dist/context/exchange-summariser.d.ts +80 -0
  17. package/dist/context/exchange-summariser.js +261 -0
  18. package/dist/context/health-monitor.d.ts +97 -0
  19. package/dist/context/health-monitor.example.d.ts +1 -0
  20. package/dist/context/health-monitor.example.js +164 -0
  21. package/dist/context/health-monitor.js +210 -0
  22. package/dist/context/importance-scorer.d.ts +94 -0
  23. package/dist/context/importance-scorer.example.d.ts +1 -0
  24. package/dist/context/importance-scorer.example.js +140 -0
  25. package/dist/context/importance-scorer.js +187 -0
  26. package/dist/context/index.d.ts +9 -0
  27. package/dist/context/index.js +16 -0
  28. package/dist/context/session-helper.d.ts +10 -0
  29. package/dist/context/session-helper.js +51 -0
  30. package/dist/context/session-store.d.ts +94 -0
  31. package/dist/context/session-store.js +286 -0
  32. package/dist/context/usage-estimator.d.ts +131 -0
  33. package/dist/context/usage-estimator.js +260 -0
  34. package/dist/context/usage-estimator.test.d.ts +1 -0
  35. package/dist/context/usage-estimator.test.js +208 -0
  36. package/dist/context-cli.d.ts +16 -0
  37. package/dist/context-cli.js +309 -0
  38. package/dist/evaluation/build-dataset.d.ts +1 -0
  39. package/dist/evaluation/build-dataset.js +135 -0
  40. package/dist/evaluation/threshold-eval.d.ts +63 -0
  41. package/dist/evaluation/threshold-eval.js +250 -0
  42. package/dist/handlers/codedna-handlers.d.ts +2 -2
  43. package/dist/handlers/tool-handlers.js +126 -165
  44. package/dist/helpers/api-client.d.ts +5 -1
  45. package/dist/helpers/api-client.js +3 -1
  46. package/dist/helpers/compact-formatter.d.ts +51 -0
  47. package/dist/helpers/compact-formatter.js +130 -0
  48. package/dist/helpers/engagement-tracker.d.ts +10 -0
  49. package/dist/helpers/engagement-tracker.js +61 -0
  50. package/dist/helpers/error-tracking.js +1 -1
  51. package/dist/helpers/session-validation.d.ts +76 -0
  52. package/dist/helpers/session-validation.js +221 -0
  53. package/dist/helpers/usage-analytics.js +1 -1
  54. package/dist/hooks/index.d.ts +4 -0
  55. package/dist/hooks/index.js +6 -0
  56. package/dist/hooks/post-tool-use-hook-cli.d.ts +2 -0
  57. package/dist/hooks/post-tool-use-hook-cli.js +34 -0
  58. package/dist/hooks/post-tool-use.d.ts +67 -0
  59. package/dist/hooks/post-tool-use.js +234 -0
  60. package/dist/hooks/stop-hook-cli.d.ts +2 -0
  61. package/dist/hooks/stop-hook-cli.js +34 -0
  62. package/dist/hooks/stop.d.ts +64 -0
  63. package/dist/hooks/stop.js +192 -0
  64. package/dist/index.d.ts +3 -0
  65. package/dist/index.js +2 -0
  66. package/dist/logger.d.ts +1 -1
  67. package/dist/logger.js +4 -0
  68. package/dist/resources.js +3 -0
  69. package/dist/setup.js +206 -2
  70. package/dist/templates/claude-md.d.ts +1 -1
  71. package/dist/templates/claude-md.js +23 -35
  72. package/dist/templates/worker-prompt.js +35 -202
  73. package/dist/tools.js +26 -20
  74. package/package.json +6 -2
@@ -0,0 +1,164 @@
1
+ // =============================================================================
2
+ // Health Monitor Usage Example
3
+ // =============================================================================
4
+ // Demonstrates how to use the health monitor to track and calibrate
5
+ // context estimation accuracy.
6
+ // =============================================================================
7
+ import { getHealthMonitor } from './index.js';
8
+ // =============================================================================
9
+ // Example 1: Basic Health Check
10
+ // =============================================================================
11
+ function exampleBasicHealthCheck() {
12
+ console.log('\n=== Example 1: Basic Health Check ===\n');
13
+ const monitor = getHealthMonitor();
14
+ const session = {
15
+ session_id: 'example-session-1',
16
+ started_at: new Date(),
17
+ injected_facts: [],
18
+ };
19
+ const health = monitor.checkHealth(session);
20
+ console.log('Health Status:');
21
+ console.log(` Estimated Fill: ${(health.estimatedFill * 100).toFixed(1)}%`);
22
+ console.log(` Calibration Factor: ${health.calibrationFactor.toFixed(3)}`);
23
+ console.log(` Drift Warning: ${health.driftWarning}`);
24
+ console.log(` Recommendation: ${health.recommendation}`);
25
+ console.log('\nMetrics:');
26
+ console.log(` Sessions Monitored: ${health.metrics.sessionsMonitored}`);
27
+ console.log(` Average Drift: ${(health.metrics.avgDrift * 100).toFixed(1)}%`);
28
+ console.log(` Last Calibration: ${health.metrics.lastCalibration || 'Never'}`);
29
+ }
30
+ // =============================================================================
31
+ // Example 2: Calibration with Actual Usage
32
+ // =============================================================================
33
+ function exampleCalibration() {
34
+ console.log('\n=== Example 2: Calibration with Actual Usage ===\n');
35
+ const monitor = getHealthMonitor();
36
+ const session = {
37
+ session_id: 'example-session-2',
38
+ started_at: new Date(),
39
+ injected_facts: [],
40
+ };
41
+ // Simulate receiving actual usage data from /context command
42
+ console.log('Calibrating with actual usage data...\n');
43
+ // Session 1: Actual usage 60%, estimated 50%
44
+ monitor.calibrate(session, 0.6);
45
+ console.log('Session 1: Actual 60%, Estimated 50%');
46
+ // Session 2: Actual usage 65%, estimated 50%
47
+ monitor.calibrate(session, 0.65);
48
+ console.log('Session 2: Actual 65%, Estimated 50%');
49
+ // Session 3: Actual usage 70%, estimated 50%
50
+ monitor.calibrate(session, 0.7);
51
+ console.log('Session 3: Actual 70%, Estimated 50%');
52
+ // Check health after calibration
53
+ const health = monitor.checkHealth(session);
54
+ console.log('\nHealth after calibration:');
55
+ console.log(` Calibration Factor: ${health.calibrationFactor.toFixed(3)}`);
56
+ console.log(` Drift Warning: ${health.driftWarning}`);
57
+ console.log(` Average Drift: ${(health.metrics.avgDrift * 100).toFixed(1)}%`);
58
+ console.log(` Recommendation: ${health.recommendation}`);
59
+ }
60
+ // =============================================================================
61
+ // Example 3: Drift History Analysis
62
+ // =============================================================================
63
+ function exampleDriftHistory() {
64
+ console.log('\n=== Example 3: Drift History Analysis ===\n');
65
+ const monitor = getHealthMonitor();
66
+ const session = {
67
+ session_id: 'example-session-3',
68
+ started_at: new Date(),
69
+ injected_facts: [],
70
+ };
71
+ // Add some calibration samples
72
+ const samples = [0.55, 0.58, 0.62, 0.65, 0.70];
73
+ samples.forEach((actual, index) => {
74
+ monitor.calibrate(session, actual);
75
+ console.log(`Sample ${index + 1}: Actual ${(actual * 100).toFixed(0)}%`);
76
+ });
77
+ // Get drift history
78
+ console.log('\nDrift History (newest first):');
79
+ const history = monitor.getDriftHistory();
80
+ history.slice(0, 5).forEach((record, index) => {
81
+ console.log(` ${index + 1}. ${record.timestamp.toISOString()}: ` +
82
+ `Est: ${(record.estimated * 100).toFixed(1)}%, ` +
83
+ `Actual: ${(record.actual * 100).toFixed(1)}%, ` +
84
+ `Drift: ${record.drift > 0 ? '+' : ''}${(record.drift * 100).toFixed(1)}%`);
85
+ });
86
+ }
87
+ // =============================================================================
88
+ // Example 4: Integration with Context Management
89
+ // =============================================================================
90
+ function exampleIntegration() {
91
+ console.log('\n=== Example 4: Integration Pattern ===\n');
92
+ const monitor = getHealthMonitor();
93
+ // Simulated context management flow
94
+ const session = {
95
+ session_id: 'example-session-4',
96
+ started_at: new Date(),
97
+ injected_facts: [],
98
+ };
99
+ console.log('Context Management Flow:\n');
100
+ // 1. Check health before injection
101
+ console.log('1. Check health status');
102
+ const healthBefore = monitor.checkHealth(session);
103
+ console.log(` Current calibration factor: ${healthBefore.calibrationFactor.toFixed(3)}`);
104
+ // 2. Use calibrated estimates for injection decisions
105
+ console.log('\n2. Use calibrated estimates');
106
+ const baseEstimate = 0.5;
107
+ const calibratedEstimate = baseEstimate * healthBefore.calibrationFactor;
108
+ console.log(` Base estimate: ${(baseEstimate * 100).toFixed(1)}%`);
109
+ console.log(` Calibrated estimate: ${(calibratedEstimate * 100).toFixed(1)}%`);
110
+ // 3. After session, calibrate with actual usage
111
+ console.log('\n3. Calibrate with actual usage');
112
+ const actualUsage = 0.65;
113
+ monitor.calibrate(session, actualUsage);
114
+ console.log(` Actual usage: ${(actualUsage * 100).toFixed(1)}%`);
115
+ // 4. Check updated health
116
+ console.log('\n4. Check updated health');
117
+ const healthAfter = monitor.checkHealth(session);
118
+ console.log(` New calibration factor: ${healthAfter.calibrationFactor.toFixed(3)}`);
119
+ console.log(` Drift warning: ${healthAfter.driftWarning}`);
120
+ if (healthAfter.driftWarning) {
121
+ console.log(` ⚠️ ${healthAfter.recommendation}`);
122
+ }
123
+ }
124
+ // =============================================================================
125
+ // Example 5: Handling Drift Warnings
126
+ // =============================================================================
127
+ function exampleDriftWarnings() {
128
+ console.log('\n=== Example 5: Handling Drift Warnings ===\n');
129
+ const monitor = getHealthMonitor();
130
+ monitor.reset(); // Start fresh
131
+ const session = {
132
+ session_id: 'example-session-5',
133
+ started_at: new Date(),
134
+ injected_facts: [],
135
+ };
136
+ console.log('Simulating consistent underestimation:\n');
137
+ // Simulate consistent underestimation (actual >> estimated)
138
+ for (let i = 0; i < 5; i++) {
139
+ const actual = 0.75 + i * 0.02; // Gradually increasing
140
+ monitor.calibrate(session, actual);
141
+ console.log(`Calibration ${i + 1}: Actual ${(actual * 100).toFixed(1)}%`);
142
+ }
143
+ const health = monitor.checkHealth(session);
144
+ console.log('\nHealth Check Result:');
145
+ console.log(` ⚠️ Drift Warning: ${health.driftWarning}`);
146
+ console.log(` 📊 Average Drift: ${(health.metrics.avgDrift * 100).toFixed(1)}%`);
147
+ console.log(` 🔧 Calibration Factor: ${health.calibrationFactor.toFixed(3)}`);
148
+ console.log(`\n💡 ${health.recommendation}`);
149
+ console.log('\nNext steps:');
150
+ console.log(' - Future estimates will be multiplied by calibration factor');
151
+ console.log(' - Monitor drift over time to ensure accuracy improves');
152
+ console.log(' - Consider more aggressive eviction if needed');
153
+ }
154
+ // =============================================================================
155
+ // Run All Examples
156
+ // =============================================================================
157
+ if (import.meta.url === `file://${process.argv[1]}`) {
158
+ exampleBasicHealthCheck();
159
+ exampleCalibration();
160
+ exampleDriftHistory();
161
+ exampleIntegration();
162
+ exampleDriftWarnings();
163
+ console.log('\n=== Examples Complete ===\n');
164
+ }
@@ -0,0 +1,210 @@
1
+ // =============================================================================
2
+ // Health Monitor - Context estimation accuracy tracking
3
+ // =============================================================================
4
+ // Monitors drift between estimated and actual token usage to calibrate
5
+ // estimates and warn when accuracy degrades.
6
+ //
7
+ // Calibration Logic:
8
+ // - Records drift when actual fill data is available
9
+ // - Adjusts future estimates by calibration factor
10
+ // - Warns if drift exceeds 10%
11
+ // =============================================================================
12
+ // -----------------------------------------------------------------------------
13
+ // Configuration
14
+ // -----------------------------------------------------------------------------
15
+ const HEALTH_CONFIG = {
16
+ /** Maximum number of drift records to store in memory */
17
+ MAX_DRIFT_HISTORY: 100,
18
+ /** Drift threshold for warnings (10%) */
19
+ DRIFT_WARNING_THRESHOLD: 0.1,
20
+ /** Number of samples needed before adjusting calibration */
21
+ MIN_SAMPLES_FOR_CALIBRATION: 3,
22
+ /** Weight of new samples in moving average (0-1) */
23
+ CALIBRATION_SMOOTHING: 0.3,
24
+ };
25
+ // -----------------------------------------------------------------------------
26
+ // Health Monitor Implementation
27
+ // -----------------------------------------------------------------------------
28
+ export class HealthMonitor {
29
+ driftHistory = [];
30
+ calibrationFactor = 1.0;
31
+ lastCalibrationDate = null;
32
+ /**
33
+ * Check health status of session estimation
34
+ *
35
+ * @param session - Current session state
36
+ * @returns Health status with metrics and recommendations
37
+ */
38
+ checkHealth(session) {
39
+ const estimatedFill = this.getEstimatedFill(session);
40
+ const avgDrift = this.calculateAverageDrift();
41
+ const driftWarning = Math.abs(avgDrift) > HEALTH_CONFIG.DRIFT_WARNING_THRESHOLD;
42
+ return {
43
+ estimatedFill,
44
+ calibrationFactor: this.calibrationFactor,
45
+ driftWarning,
46
+ recommendation: this.generateRecommendation(avgDrift, driftWarning),
47
+ metrics: {
48
+ sessionsMonitored: this.driftHistory.length,
49
+ avgDrift,
50
+ lastCalibration: this.lastCalibrationDate,
51
+ },
52
+ };
53
+ }
54
+ /**
55
+ * Calibrate estimates using actual fill measurement
56
+ * Records drift and adjusts calibration factor if needed
57
+ *
58
+ * @param session - Current session state
59
+ * @param actualFill - Actual token usage (0.0 to 1.0)
60
+ */
61
+ calibrate(session, actualFill) {
62
+ const estimatedFill = this.getEstimatedFill(session);
63
+ const drift = actualFill - estimatedFill;
64
+ const driftPercent = drift / actualFill;
65
+ // Record drift
66
+ this.recordDrift(estimatedFill, actualFill, drift);
67
+ // Update calibration if we have enough samples
68
+ if (this.driftHistory.length >= HEALTH_CONFIG.MIN_SAMPLES_FOR_CALIBRATION) {
69
+ this.updateCalibrationFactor();
70
+ }
71
+ }
72
+ /**
73
+ * Get current calibration factor
74
+ * Multiply estimated tokens by this factor to get calibrated estimate
75
+ *
76
+ * @returns Current calibration factor
77
+ */
78
+ getCalibrationFactor() {
79
+ return this.calibrationFactor;
80
+ }
81
+ /**
82
+ * Get drift history for analysis
83
+ *
84
+ * @returns Array of drift records (newest first)
85
+ */
86
+ getDriftHistory() {
87
+ return [...this.driftHistory].reverse();
88
+ }
89
+ /**
90
+ * Clear drift history and reset calibration
91
+ * Useful when estimation algorithm changes
92
+ */
93
+ reset() {
94
+ this.driftHistory = [];
95
+ this.calibrationFactor = 1.0;
96
+ this.lastCalibrationDate = null;
97
+ }
98
+ // ---------------------------------------------------------------------------
99
+ // Private Helpers
100
+ // ---------------------------------------------------------------------------
101
+ /**
102
+ * Get estimated fill from session state
103
+ * This would normally come from the usage estimator
104
+ */
105
+ getEstimatedFill(session) {
106
+ // In practice, this would call usageEstimator.getContextFill(session)
107
+ // For now, return a placeholder that accounts for calibration
108
+ return 0.5 * this.calibrationFactor; // Placeholder
109
+ }
110
+ /**
111
+ * Record a drift measurement
112
+ */
113
+ recordDrift(estimated, actual, drift) {
114
+ const record = {
115
+ timestamp: new Date(),
116
+ estimated,
117
+ actual,
118
+ drift,
119
+ };
120
+ this.driftHistory.push(record);
121
+ // Trim history if it exceeds max size
122
+ if (this.driftHistory.length > HEALTH_CONFIG.MAX_DRIFT_HISTORY) {
123
+ this.driftHistory.shift(); // Remove oldest
124
+ }
125
+ }
126
+ /**
127
+ * Calculate average drift from recent history
128
+ * Uses exponential weighting (recent samples weighted more)
129
+ */
130
+ calculateAverageDrift() {
131
+ if (this.driftHistory.length === 0) {
132
+ return 0;
133
+ }
134
+ // Use last 10 samples for average
135
+ const recentSamples = this.driftHistory.slice(-10);
136
+ let weightedSum = 0;
137
+ let totalWeight = 0;
138
+ recentSamples.forEach((record, index) => {
139
+ // Exponential weight: newer samples weighted more heavily
140
+ const weight = Math.exp(index / recentSamples.length);
141
+ const driftPercent = record.drift / record.actual;
142
+ weightedSum += driftPercent * weight;
143
+ totalWeight += weight;
144
+ });
145
+ return weightedSum / totalWeight;
146
+ }
147
+ /**
148
+ * Update calibration factor based on drift history
149
+ * Uses exponential moving average to smooth adjustments
150
+ */
151
+ updateCalibrationFactor() {
152
+ const avgDrift = this.calculateAverageDrift();
153
+ // Calculate new factor: if we're consistently underestimating (positive drift),
154
+ // increase the factor; if overestimating, decrease it
155
+ const targetFactor = 1 / (1 - avgDrift);
156
+ // Smooth the adjustment using exponential moving average
157
+ this.calibrationFactor =
158
+ this.calibrationFactor * (1 - HEALTH_CONFIG.CALIBRATION_SMOOTHING) +
159
+ targetFactor * HEALTH_CONFIG.CALIBRATION_SMOOTHING;
160
+ this.lastCalibrationDate = new Date();
161
+ }
162
+ /**
163
+ * Generate health recommendation based on drift
164
+ */
165
+ generateRecommendation(avgDrift, driftWarning) {
166
+ if (!driftWarning) {
167
+ return 'Estimation accuracy is good. No action needed.';
168
+ }
169
+ const driftPercent = Math.abs(avgDrift * 100).toFixed(1);
170
+ if (avgDrift > 0) {
171
+ // Underestimating (actual usage higher than estimated)
172
+ return `Warning: Estimates are ${driftPercent}% too low. Context window may fill faster than expected. Consider more aggressive eviction.`;
173
+ }
174
+ else {
175
+ // Overestimating (actual usage lower than estimated)
176
+ return `Warning: Estimates are ${driftPercent}% too high. Context window has more capacity than estimated. Can inject more facts safely.`;
177
+ }
178
+ }
179
+ }
180
+ // -----------------------------------------------------------------------------
181
+ // Factory
182
+ // -----------------------------------------------------------------------------
183
+ /**
184
+ * Create a new health monitor instance
185
+ */
186
+ export function createHealthMonitor() {
187
+ return new HealthMonitor();
188
+ }
189
+ // -----------------------------------------------------------------------------
190
+ // Singleton Instance
191
+ // -----------------------------------------------------------------------------
192
+ let monitorInstance = null;
193
+ /**
194
+ * Get or create the singleton health monitor instance
195
+ */
196
+ export function getHealthMonitor() {
197
+ if (!monitorInstance) {
198
+ monitorInstance = new HealthMonitor();
199
+ }
200
+ return monitorInstance;
201
+ }
202
+ /**
203
+ * Reset the singleton instance (for testing)
204
+ */
205
+ export function resetHealthMonitor() {
206
+ if (monitorInstance) {
207
+ monitorInstance.reset();
208
+ }
209
+ monitorInstance = null;
210
+ }
@@ -0,0 +1,94 @@
1
+ import type { ScoredFact } from '@claudetools/shared';
2
+ /**
3
+ * Fact that has been injected into the session context
4
+ * Tracks injection time and reference patterns for decay calculation
5
+ */
6
+ export interface InjectedFact extends ScoredFact {
7
+ injected_at: Date;
8
+ last_referenced?: Date;
9
+ }
10
+ /**
11
+ * Session state tracking for importance scoring
12
+ * Contains session metadata needed for recency calculations
13
+ */
14
+ export interface SessionState {
15
+ session_id: string;
16
+ started_at: Date;
17
+ injected_facts: InjectedFact[];
18
+ }
19
+ /**
20
+ * Importance level from fact metadata
21
+ */
22
+ export type ImportanceLevel = 'critical' | 'high' | 'normal';
23
+ /**
24
+ * Scored fact with computed importance
25
+ */
26
+ export interface ScoredImportance {
27
+ fact: InjectedFact;
28
+ score: number;
29
+ breakdown: {
30
+ base: number;
31
+ timeDecay: number;
32
+ referenceBoost: number;
33
+ recencyBoost: number;
34
+ };
35
+ }
36
+ export declare class ImportanceScorer {
37
+ /**
38
+ * Calculate dynamic importance score for a single fact
39
+ *
40
+ * @param fact - The injected fact to score
41
+ * @param session - Current session state
42
+ * @returns Importance score between 0.0 and 1.0
43
+ */
44
+ calculateImportance(fact: InjectedFact, session: SessionState): number;
45
+ /**
46
+ * Calculate importance with component breakdown for debugging
47
+ *
48
+ * @param fact - The injected fact to score
49
+ * @param session - Current session state
50
+ * @returns Scored fact with breakdown
51
+ */
52
+ calculateWithBreakdown(fact: InjectedFact, session: SessionState): ScoredImportance;
53
+ /**
54
+ * Score all facts in a session
55
+ *
56
+ * @param session - Session state with injected facts
57
+ * @returns Array of scored facts sorted by score (descending)
58
+ */
59
+ scoreAllFacts(session: SessionState): ScoredImportance[];
60
+ /**
61
+ * Get facts that should be evicted (lowest importance scores)
62
+ *
63
+ * @param session - Session state
64
+ * @param count - Number of facts to evict
65
+ * @returns Facts to evict (lowest scores first)
66
+ */
67
+ getEvictionCandidates(session: SessionState, count: number): InjectedFact[];
68
+ /**
69
+ * Get facts above a minimum importance threshold
70
+ *
71
+ * @param session - Session state
72
+ * @param minScore - Minimum score threshold (0.0 to 1.0)
73
+ * @returns Facts above threshold
74
+ */
75
+ getFactsAboveThreshold(session: SessionState, minScore: number): InjectedFact[];
76
+ /**
77
+ * Extract importance level from fact metadata
78
+ */
79
+ private extractImportanceLevel;
80
+ /**
81
+ * Calculate reference boost
82
+ * Recently-referenced facts get a boost to stay in context longer
83
+ */
84
+ private calculateReferenceBoost;
85
+ /**
86
+ * Calculate recency boost
87
+ * Newer injections in the session get a boost
88
+ */
89
+ private calculateRecencyBoost;
90
+ }
91
+ /**
92
+ * Create a new importance scorer instance
93
+ */
94
+ export declare function createImportanceScorer(): ImportanceScorer;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,140 @@
1
+ // =============================================================================
2
+ // Importance Scorer - Example Usage
3
+ // =============================================================================
4
+ // Demonstrates the importance decay algorithm for automatic context management
5
+ // =============================================================================
6
+ import { createImportanceScorer } from './importance-scorer.js';
7
+ // -----------------------------------------------------------------------------
8
+ // Example Session Setup
9
+ // -----------------------------------------------------------------------------
10
+ // Create a session that started 1 hour ago
11
+ const sessionStartTime = new Date(Date.now() - 60 * 60 * 1000);
12
+ // Create facts with different importance levels and injection times
13
+ const facts = [
14
+ // Critical fact injected 5 minutes ago
15
+ {
16
+ edge_id: 'fact1',
17
+ source_entity_id: 'component_a',
18
+ target_entity_id: 'pattern_x',
19
+ relation_type: 'USES',
20
+ fact: 'ComponentA uses PatternX for state management',
21
+ created_at: new Date().toISOString(),
22
+ metadata: {
23
+ critical: true,
24
+ category: 'architecture',
25
+ },
26
+ injected_at: new Date(Date.now() - 5 * 60 * 1000), // 5 minutes ago
27
+ },
28
+ // High importance fact injected 15 minutes ago (still within half-life)
29
+ {
30
+ edge_id: 'fact2',
31
+ source_entity_id: 'bug_123',
32
+ target_entity_id: 'fix_abc',
33
+ relation_type: 'HAD_BUG',
34
+ fact: 'Bug 123 was fixed by implementing retry logic',
35
+ created_at: new Date().toISOString(),
36
+ metadata: {
37
+ important: true,
38
+ category: 'decision',
39
+ },
40
+ injected_at: new Date(Date.now() - 15 * 60 * 1000), // 15 minutes ago
41
+ },
42
+ // Normal fact injected 45 minutes ago (past half-life, should decay)
43
+ {
44
+ edge_id: 'fact3',
45
+ source_entity_id: 'user',
46
+ target_entity_id: 'preference',
47
+ relation_type: 'PREFERS',
48
+ fact: 'User prefers TypeScript over JavaScript',
49
+ created_at: new Date().toISOString(),
50
+ metadata: {
51
+ category: 'preference',
52
+ },
53
+ injected_at: new Date(Date.now() - 45 * 60 * 1000), // 45 minutes ago
54
+ },
55
+ // High importance fact injected 20 minutes ago, referenced 2 minutes ago
56
+ {
57
+ edge_id: 'fact4',
58
+ source_entity_id: 'module_y',
59
+ target_entity_id: 'dependency_z',
60
+ relation_type: 'DEPENDS_ON',
61
+ fact: 'ModuleY depends on DependencyZ for authentication',
62
+ created_at: new Date().toISOString(),
63
+ metadata: {
64
+ important: true,
65
+ category: 'pattern',
66
+ },
67
+ injected_at: new Date(Date.now() - 20 * 60 * 1000), // 20 minutes ago
68
+ last_referenced: new Date(Date.now() - 2 * 60 * 1000), // Referenced 2 minutes ago
69
+ },
70
+ ];
71
+ const session = {
72
+ session_id: 'example_session',
73
+ started_at: sessionStartTime,
74
+ injected_facts: facts,
75
+ };
76
+ // -----------------------------------------------------------------------------
77
+ // Score and Display Results
78
+ // -----------------------------------------------------------------------------
79
+ const scorer = createImportanceScorer();
80
+ console.log('='.repeat(80));
81
+ console.log('Importance Scorer - Example Execution');
82
+ console.log('='.repeat(80));
83
+ console.log();
84
+ // Score all facts
85
+ const scored = scorer.scoreAllFacts(session);
86
+ console.log('Scored Facts (highest to lowest importance):');
87
+ console.log('-'.repeat(80));
88
+ scored.forEach((result, index) => {
89
+ console.log(`${index + 1}. ${result.fact.fact}`);
90
+ console.log(` Score: ${result.score.toFixed(3)}`);
91
+ console.log(` Breakdown:`);
92
+ console.log(` - Base Importance: ${result.breakdown.base.toFixed(3)}`);
93
+ console.log(` - Time Decay: ${result.breakdown.timeDecay.toFixed(3)}`);
94
+ console.log(` - Reference Boost: ${result.breakdown.referenceBoost.toFixed(3)}`);
95
+ console.log(` - Recency Boost: ${result.breakdown.recencyBoost.toFixed(3)}`);
96
+ console.log(` Injected: ${Math.round((Date.now() - result.fact.injected_at.getTime()) / 60000)} minutes ago`);
97
+ if (result.fact.last_referenced) {
98
+ console.log(` Last Referenced: ${Math.round((Date.now() - result.fact.last_referenced.getTime()) / 60000)} minutes ago`);
99
+ }
100
+ console.log();
101
+ });
102
+ // -----------------------------------------------------------------------------
103
+ // Eviction Example
104
+ // -----------------------------------------------------------------------------
105
+ console.log('='.repeat(80));
106
+ console.log('Eviction Candidates (lowest 2 scores):');
107
+ console.log('-'.repeat(80));
108
+ const evictionCandidates = scorer.getEvictionCandidates(session, 2);
109
+ evictionCandidates.forEach((fact, index) => {
110
+ console.log(`${index + 1}. ${fact.fact}`);
111
+ });
112
+ console.log();
113
+ // -----------------------------------------------------------------------------
114
+ // Threshold Example
115
+ // -----------------------------------------------------------------------------
116
+ console.log('='.repeat(80));
117
+ console.log('Facts Above Threshold (min score: 0.5):');
118
+ console.log('-'.repeat(80));
119
+ const aboveThreshold = scorer.getFactsAboveThreshold(session, 0.5);
120
+ aboveThreshold.forEach((fact, index) => {
121
+ console.log(`${index + 1}. ${fact.fact}`);
122
+ });
123
+ console.log();
124
+ // -----------------------------------------------------------------------------
125
+ // Algorithm Verification
126
+ // -----------------------------------------------------------------------------
127
+ console.log('='.repeat(80));
128
+ console.log('Algorithm Verification:');
129
+ console.log('-'.repeat(80));
130
+ console.log('✓ Base importance levels: critical (1.0), high (0.7), normal (0.4)');
131
+ console.log('✓ Time decay: Exponential with 30-minute half-life');
132
+ console.log('✓ Reference boost: Recent references keep facts longer');
133
+ console.log('✓ Recency boost: Newer injections weighted higher');
134
+ console.log('✓ Score range: All scores between 0.0 and 1.0');
135
+ console.log();
136
+ console.log('Expected behavior:');
137
+ console.log(' - Critical architecture fact should score highest (recently injected)');
138
+ console.log(' - Recently referenced fact should get boost despite age');
139
+ console.log(' - Old normal fact should score lowest (past half-life, no boost)');
140
+ console.log('='.repeat(80));