@ulrichc1/sparn 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -221,6 +221,27 @@ interface UIConfig {
221
221
  /** Verbose logging (default: false) */
222
222
  verbose: boolean;
223
223
  }
224
+ /**
225
+ * Real-time optimization configuration.
226
+ */
227
+ interface RealtimeConfig {
228
+ /** Target token budget for optimized context (default: 50000) */
229
+ tokenBudget: number;
230
+ /** Token threshold that triggers auto-optimization (default: 80000) */
231
+ autoOptimizeThreshold: number;
232
+ /** File patterns to watch for changes (default: ['**\/*.jsonl']) */
233
+ watchPatterns: string[];
234
+ /** Daemon PID file path (default: '.sparn/daemon.pid') */
235
+ pidFile: string;
236
+ /** Daemon log file path (default: '.sparn/daemon.log') */
237
+ logFile: string;
238
+ /** Debounce delay in milliseconds for file changes (default: 5000) */
239
+ debounceMs: number;
240
+ /** Enable incremental optimization (default: true) */
241
+ incremental: boolean;
242
+ /** Sliding window size for context entries (default: 500) */
243
+ windowSize: number;
244
+ }
224
245
  /**
225
246
  * Complete Sparn configuration.
226
247
  */
@@ -232,6 +253,8 @@ interface SparnConfig {
232
253
  ui: UIConfig;
233
254
  /** Auto-consolidation interval in hours, or null for manual */
234
255
  autoConsolidate: number | null;
256
+ /** Real-time optimization settings */
257
+ realtime: RealtimeConfig;
235
258
  }
236
259
  /**
237
260
  * Default configuration values.
@@ -296,6 +319,91 @@ interface BTSPEmbedder {
296
319
  */
297
320
  declare function createBTSPEmbedder(): BTSPEmbedder;
298
321
 
322
+ /**
323
+ * Sparse pruner types.
324
+ * Implements sparse coding principle from neuroscience.
325
+ */
326
+
327
+ /**
328
+ * Result of a pruning operation.
329
+ */
330
+ interface PruneResult {
331
+ /** Entries kept after pruning */
332
+ kept: MemoryEntry[];
333
+ /** Entries removed during pruning */
334
+ removed: MemoryEntry[];
335
+ /** Original token count before pruning */
336
+ originalTokens: number;
337
+ /** Token count after pruning */
338
+ prunedTokens: number;
339
+ }
340
+
341
+ /**
342
+ * Budget-Aware Pruner - Token budget optimization
343
+ *
344
+ * Unlike SparsePruner which keeps top N% entries, BudgetPruner fits entries
345
+ * within a target token budget using priority scoring that combines:
346
+ * - TF-IDF relevance
347
+ * - Engram decay
348
+ * - Confidence state multipliers
349
+ * - BTSP bypass (always included)
350
+ *
351
+ * Target use case: Real-time optimization for Opus model (~50K token budget)
352
+ */
353
+
354
+ interface BudgetPrunerConfig {
355
+ /** Target token budget */
356
+ tokenBudget: number;
357
+ /** Decay configuration */
358
+ decay: {
359
+ defaultTTL: number;
360
+ decayThreshold: number;
361
+ };
362
+ /** State multipliers */
363
+ states: {
364
+ activeThreshold: number;
365
+ readyThreshold: number;
366
+ };
367
+ }
368
+ interface BudgetPruner {
369
+ /**
370
+ * Prune entries to fit within token budget
371
+ * @param entries - Memory entries to prune
372
+ * @param budget - Optional override budget (uses config default if not provided)
373
+ * @returns Result with kept/removed entries and budget utilization
374
+ */
375
+ pruneToFit(entries: MemoryEntry[], budget?: number): PruneResult & {
376
+ budgetUtilization: number;
377
+ };
378
+ /**
379
+ * Calculate priority score for an entry
380
+ * @param entry - Entry to score
381
+ * @param allEntries - All entries for TF-IDF calculation
382
+ * @returns Priority score (higher = more important)
383
+ */
384
+ priorityScore(entry: MemoryEntry, allEntries: MemoryEntry[]): number;
385
+ }
386
+ /**
387
+ * Create a budget-aware pruner instance
388
+ * @param config - Pruner configuration
389
+ * @returns BudgetPruner instance
390
+ */
391
+ declare function createBudgetPruner(config: BudgetPrunerConfig): BudgetPruner;
392
+ /**
393
+ * Helper to create budget pruner from RealtimeConfig
394
+ * @param realtimeConfig - Realtime configuration
395
+ * @param decayConfig - Decay configuration
396
+ * @param statesConfig - States configuration
397
+ * @returns BudgetPruner instance
398
+ */
399
+ declare function createBudgetPrunerFromConfig(realtimeConfig: RealtimeConfig, decayConfig: {
400
+ defaultTTL: number;
401
+ decayThreshold: number;
402
+ }, statesConfig: {
403
+ activeThreshold: number;
404
+ readyThreshold: number;
405
+ }): BudgetPruner;
406
+
299
407
  /**
300
408
  * Confidence States - Implements multi-state synapses
301
409
  *
@@ -336,6 +444,158 @@ interface ConfidenceStates {
336
444
  */
337
445
  declare function createConfidenceStates(config: ConfidenceStatesConfig): ConfidenceStates;
338
446
 
447
+ /**
448
+ * Incremental Optimizer - Cache-based delta processing
449
+ *
450
+ * Optimizes performance for real-time scenarios by:
451
+ * - Caching entry scores by content hash
452
+ * - Only recomputing scores for new/changed entries
453
+ * - Pre-computing and caching document frequency tables
454
+ * - Periodically forcing full re-optimization to prevent drift
455
+ *
456
+ * Target: <50ms for incremental updates on 100K token contexts
457
+ */
458
+
459
+ interface IncrementalOptimizerConfig extends BudgetPrunerConfig {
460
+ /** Force full re-optimization every N incremental updates */
461
+ fullOptimizationInterval: number;
462
+ }
463
+ interface IncrementalOptimizerState {
464
+ /** Entry cache keyed by content hash */
465
+ entryCache: Map<string, {
466
+ entry: MemoryEntry;
467
+ score: number;
468
+ timestamp: number;
469
+ }>;
470
+ /** Document frequency table for IDF calculation */
471
+ documentFrequency: Map<string, number>;
472
+ /** Total document count for IDF */
473
+ totalDocuments: number;
474
+ /** Incremental update counter */
475
+ updateCount: number;
476
+ /** Last full optimization timestamp */
477
+ lastFullOptimization: number;
478
+ }
479
+ interface IncrementalOptimizer {
480
+ /**
481
+ * Optimize incrementally (only process new/changed entries)
482
+ * @param newEntries - New entries to add
483
+ * @param budget - Optional budget override
484
+ * @returns Prune result with budget utilization
485
+ */
486
+ optimizeIncremental(newEntries: MemoryEntry[], budget?: number): PruneResult & {
487
+ budgetUtilization: number;
488
+ };
489
+ /**
490
+ * Optimize fully (recompute all scores)
491
+ * @param allEntries - All entries to optimize
492
+ * @param budget - Optional budget override
493
+ * @returns Prune result with budget utilization
494
+ */
495
+ optimizeFull(allEntries: MemoryEntry[], budget?: number): PruneResult & {
496
+ budgetUtilization: number;
497
+ };
498
+ /**
499
+ * Get current optimizer state (for serialization)
500
+ * @returns Serializable state object
501
+ */
502
+ getState(): IncrementalOptimizerState;
503
+ /**
504
+ * Restore optimizer state (from serialization)
505
+ * @param state - State to restore
506
+ */
507
+ restoreState(state: IncrementalOptimizerState): void;
508
+ /**
509
+ * Reset optimizer state (clear all caches)
510
+ */
511
+ reset(): void;
512
+ /**
513
+ * Get cache statistics
514
+ * @returns Cache stats
515
+ */
516
+ getStats(): {
517
+ cachedEntries: number;
518
+ uniqueTerms: number;
519
+ totalDocuments: number;
520
+ updateCount: number;
521
+ lastFullOptimization: number;
522
+ };
523
+ }
524
+ /**
525
+ * Create an incremental optimizer instance
526
+ * @param config - Optimizer configuration
527
+ * @returns IncrementalOptimizer instance
528
+ */
529
+ declare function createIncrementalOptimizer(config: IncrementalOptimizerConfig): IncrementalOptimizer;
530
+
531
+ /**
532
+ * Streaming Context Pipeline - Real-time sliding window buffer
533
+ *
534
+ * Maintains an optimized context in real-time by:
535
+ * - Ingesting new content as it arrives
536
+ * - Storing entries by priority internally (for eviction decisions)
537
+ * - Outputting in chronological order (for conversation coherence)
538
+ * - Evicting lowest-priority entries when budget exceeded
539
+ * - Using IncrementalOptimizer for fast delta processing
540
+ */
541
+
542
+ interface ContextPipelineConfig extends IncrementalOptimizerConfig {
543
+ /** Sliding window size (max entries to keep) */
544
+ windowSize: number;
545
+ }
546
+ interface ContextPipelineStats {
547
+ /** Total entries ingested */
548
+ totalIngested: number;
549
+ /** Current entry count */
550
+ currentEntries: number;
551
+ /** Current token count */
552
+ currentTokens: number;
553
+ /** Budget utilization (0.0-1.0) */
554
+ budgetUtilization: number;
555
+ /** Evicted entry count */
556
+ evictedEntries: number;
557
+ /** Optimizer stats */
558
+ optimizer: {
559
+ cachedEntries: number;
560
+ uniqueTerms: number;
561
+ updateCount: number;
562
+ };
563
+ }
564
+ interface ContextPipeline {
565
+ /**
566
+ * Ingest new content into the pipeline
567
+ * @param content - Raw content string
568
+ * @param metadata - Optional metadata to attach to entries
569
+ * @returns Number of entries ingested
570
+ */
571
+ ingest(content: string, metadata?: Record<string, unknown>): number;
572
+ /**
573
+ * Get current optimized context (chronologically ordered)
574
+ * @returns Optimized context string
575
+ */
576
+ getContext(): string;
577
+ /**
578
+ * Get current entries (chronologically ordered)
579
+ * @returns Array of memory entries
580
+ */
581
+ getEntries(): MemoryEntry[];
582
+ /**
583
+ * Get pipeline statistics
584
+ * @returns Pipeline stats
585
+ */
586
+ getStats(): ContextPipelineStats;
587
+ /**
588
+ * Clear all entries and reset state
589
+ */
590
+ clear(): void;
591
+ }
592
+ /**
593
+ * Create a context pipeline instance
594
+ * @param config - Pipeline configuration
595
+ * @returns ContextPipeline instance
596
+ */
597
+ declare function createContextPipeline(config: ContextPipelineConfig): ContextPipeline;
598
+
339
599
  /**
340
600
  * Engram Scorer - Implements engram theory (memory decay)
341
601
  *
@@ -451,25 +711,6 @@ interface SleepCompressor {
451
711
  */
452
712
  declare function createSleepCompressor(): SleepCompressor;
453
713
 
454
- /**
455
- * Sparse pruner types.
456
- * Implements sparse coding principle from neuroscience.
457
- */
458
-
459
- /**
460
- * Result of a pruning operation.
461
- */
462
- interface PruneResult {
463
- /** Entries kept after pruning */
464
- kept: MemoryEntry[];
465
- /** Entries removed during pruning */
466
- removed: MemoryEntry[];
467
- /** Original token count before pruning */
468
- originalTokens: number;
469
- /** Token count after pruning */
470
- prunedTokens: number;
471
- }
472
-
473
714
  /**
474
715
  * Sparse Pruner - Implements sparse coding principle
475
716
  *
@@ -503,6 +744,204 @@ interface SparsePruner {
503
744
  */
504
745
  declare function createSparsePruner(config: SparsePrunerConfig): SparsePruner;
505
746
 
747
+ /**
748
+ * Daemon Process Manager - Background process lifecycle management
749
+ *
750
+ * Handles:
751
+ * - Process forking and detachment
752
+ * - PID file management
753
+ * - Signal handling (SIGTERM, SIGINT)
754
+ * - Daemon start/stop/status commands
755
+ */
756
+
757
+ interface DaemonCommand {
758
+ /** Start the daemon */
759
+ start(config: SparnConfig): Promise<DaemonStartResult>;
760
+ /** Stop the daemon */
761
+ stop(config: SparnConfig): Promise<DaemonStopResult>;
762
+ /** Get daemon status */
763
+ status(config: SparnConfig): Promise<DaemonStatusResult>;
764
+ }
765
+ interface DaemonStartResult {
766
+ success: boolean;
767
+ pid?: number;
768
+ message: string;
769
+ error?: string;
770
+ }
771
+ interface DaemonStopResult {
772
+ success: boolean;
773
+ message: string;
774
+ error?: string;
775
+ }
776
+ interface DaemonStatusResult {
777
+ running: boolean;
778
+ pid?: number;
779
+ uptime?: number;
780
+ sessionsWatched?: number;
781
+ tokensSaved?: number;
782
+ message: string;
783
+ }
784
+ /**
785
+ * Create daemon command interface
786
+ * @returns DaemonCommand instance
787
+ */
788
+ declare function createDaemonCommand(): DaemonCommand;
789
+
790
+ /**
791
+ * File Tracker - Incremental file reading with byte position tracking
792
+ *
793
+ * Tracks read positions for files to enable efficient incremental reading.
794
+ * Handles JSONL partial line buffering for incomplete writes.
795
+ *
796
+ * Use case: Monitor Claude Code session JSONL files and only read new lines
797
+ * as they're appended, without re-reading the entire file.
798
+ */
799
+ interface FilePosition {
800
+ /** File path */
801
+ path: string;
802
+ /** Last read byte position */
803
+ position: number;
804
+ /** Partial line buffer (for JSONL incomplete writes) */
805
+ partialLine: string;
806
+ /** Last modification time */
807
+ lastModified: number;
808
+ /** File size at last read */
809
+ lastSize: number;
810
+ }
811
+ interface FileTracker {
812
+ /**
813
+ * Read new content from file since last read
814
+ * @param filePath - File to read
815
+ * @returns New content as array of lines (empty if no new content)
816
+ */
817
+ readNewLines(filePath: string): string[];
818
+ /**
819
+ * Get current position for a file
820
+ * @param filePath - File path
821
+ * @returns File position or null if not tracked
822
+ */
823
+ getPosition(filePath: string): FilePosition | null;
824
+ /**
825
+ * Reset position for a file (start from beginning on next read)
826
+ * @param filePath - File path
827
+ */
828
+ resetPosition(filePath: string): void;
829
+ /**
830
+ * Clear all tracked positions
831
+ */
832
+ clearAll(): void;
833
+ /**
834
+ * Get all tracked file paths
835
+ * @returns Array of tracked file paths
836
+ */
837
+ getTrackedFiles(): string[];
838
+ }
839
+ /**
840
+ * Create a file tracker instance
841
+ * @returns FileTracker instance
842
+ */
843
+ declare function createFileTracker(): FileTracker;
844
+
845
+ /**
846
+ * Session Watcher - Monitor Claude Code session files for changes
847
+ *
848
+ * Uses Node.js fs.watch to monitor ~/.claude/projects/**\/*.jsonl files.
849
+ * Debounces events and triggers optimization when token threshold exceeded.
850
+ * Maintains per-session ContextPipeline instances.
851
+ */
852
+
853
+ interface SessionWatcherConfig {
854
+ /** Sparn configuration */
855
+ config: SparnConfig;
856
+ /** Callback when optimization triggered */
857
+ onOptimize?: (sessionId: string, stats: SessionStats) => void;
858
+ /** Callback on error */
859
+ onError?: (error: Error) => void;
860
+ }
861
+ interface SessionStats {
862
+ /** Session ID */
863
+ sessionId: string;
864
+ /** Total tokens ingested */
865
+ totalTokens: number;
866
+ /** Current optimized tokens */
867
+ optimizedTokens: number;
868
+ /** Reduction percentage */
869
+ reduction: number;
870
+ /** Entry count */
871
+ entryCount: number;
872
+ /** Budget utilization */
873
+ budgetUtilization: number;
874
+ }
875
+ interface SessionWatcher {
876
+ /**
877
+ * Start watching Claude Code session files
878
+ * @returns Promise that resolves when watcher is ready
879
+ */
880
+ start(): Promise<void>;
881
+ /**
882
+ * Stop watching and cleanup
883
+ */
884
+ stop(): void;
885
+ /**
886
+ * Get statistics for all sessions
887
+ * @returns Array of session stats
888
+ */
889
+ getStats(): SessionStats[];
890
+ /**
891
+ * Get statistics for a specific session
892
+ * @param sessionId - Session ID
893
+ * @returns Session stats or null if not found
894
+ */
895
+ getSessionStats(sessionId: string): SessionStats | null;
896
+ /**
897
+ * Manually trigger optimization for a session
898
+ * @param sessionId - Session ID
899
+ */
900
+ optimizeSession(sessionId: string): void;
901
+ }
902
+ /**
903
+ * Create a session watcher instance
904
+ * @param config - Watcher configuration
905
+ * @returns SessionWatcher instance
906
+ */
907
+ declare function createSessionWatcher(config: SessionWatcherConfig): SessionWatcher;
908
+
909
+ /**
910
+ * Context Parser - Shared utilities for parsing agent contexts into memory entries
911
+ *
912
+ * Extracted from claude-code adapter to enable reuse across:
913
+ * - Adapters (claude-code, generic)
914
+ * - Real-time pipeline (streaming context)
915
+ * - Hooks (pre-prompt, post-tool-result)
916
+ */
917
+
918
+ /**
919
+ * Block type classification for Claude Code context
920
+ */
921
+ type BlockType = 'conversation' | 'tool' | 'result' | 'other';
922
+ /**
923
+ * Parse Claude Code context into memory entries
924
+ * Handles conversation turns, tool uses, and results
925
+ * @param context - Raw context string
926
+ * @returns Array of memory entries
927
+ */
928
+ declare function parseClaudeCodeContext(context: string): MemoryEntry[];
929
+ /**
930
+ * Create a memory entry from a content block
931
+ * @param content - Block content
932
+ * @param type - Block type
933
+ * @param baseTime - Base timestamp
934
+ * @returns Memory entry
935
+ */
936
+ declare function createEntry(content: string, type: BlockType, baseTime: number): MemoryEntry;
937
+ /**
938
+ * Parse generic context (fallback for non-Claude-Code agents)
939
+ * Splits on double newlines, treats as paragraphs
940
+ * @param context - Raw context string
941
+ * @returns Array of memory entries
942
+ */
943
+ declare function parseGenericContext(context: string): MemoryEntry[];
944
+
506
945
  /**
507
946
  * Content hashing utilities.
508
947
  * Uses SHA-256 for deduplication.
@@ -564,4 +1003,4 @@ declare function createLogger(verbose?: boolean): Logger;
564
1003
  */
565
1004
  declare function estimateTokens(text: string): number;
566
1005
 
567
- export { type AgentAdapter, type AgentType, type BTSPEmbedder, type ConfidenceState, type ConfidenceStates, type ConfidenceStatesConfig, type ConsolidateResult, DEFAULT_CONFIG, type DecayConfig, type DuplicateGroup, type EngramScorer, type EngramScorerConfig, type KVMemory, type LogLevel, type Logger, type MemoryEntry, type MemoryQueryFilters, type OptimizationResult, type OptimizeOptions, type PruneResult, type PruningConfig, type SleepCompressor, type SparnConfig, type SparsePruner, type SparsePrunerConfig, type StateDistribution, type StatesConfig, type UIConfig, createBTSPEmbedder, createClaudeCodeAdapter, createConfidenceStates, createEngramScorer, createGenericAdapter, createKVMemory, createLogger, createSleepCompressor, createSparsePruner, estimateTokens, hashContent };
1006
+ export { type AgentAdapter, type AgentType, type BTSPEmbedder, type BlockType, type BudgetPruner, type BudgetPrunerConfig, type ConfidenceState, type ConfidenceStates, type ConfidenceStatesConfig, type ConsolidateResult, type ContextPipeline, type ContextPipelineConfig, type ContextPipelineStats, DEFAULT_CONFIG, type DaemonCommand, type DaemonStartResult, type DaemonStatusResult, type DaemonStopResult, type DecayConfig, type DuplicateGroup, type EngramScorer, type EngramScorerConfig, type FilePosition, type FileTracker, type IncrementalOptimizer, type IncrementalOptimizerConfig, type IncrementalOptimizerState, type KVMemory, type LogLevel, type Logger, type MemoryEntry, type MemoryQueryFilters, type OptimizationResult, type OptimizeOptions, type PruneResult, type PruningConfig, type RealtimeConfig, type SessionStats, type SessionWatcher, type SessionWatcherConfig, type SleepCompressor, type SparnConfig, type SparsePruner, type SparsePrunerConfig, type StateDistribution, type StatesConfig, type UIConfig, createBTSPEmbedder, createBudgetPruner, createBudgetPrunerFromConfig, createClaudeCodeAdapter, createConfidenceStates, createContextPipeline, createDaemonCommand, createEngramScorer, createEntry, createFileTracker, createGenericAdapter, createIncrementalOptimizer, createKVMemory, createLogger, createSessionWatcher, createSleepCompressor, createSparsePruner, estimateTokens, hashContent, parseClaudeCodeContext, parseGenericContext };