All files / lib/reflection memory.ts

80.51% Statements 62/77
81.81% Branches 9/11
72.72% Functions 8/11
80.51% Lines 62/77

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 1111x       1x 1x 1x   1x   1x 1x 1x   1x 1x 1x   1x 1x 1x   1x       1x 1x                     1x       1x 1x       1x       1x 1x             1x     1x 1x 7x 7x 7x 7x   1x 1x 1x   1x   1x 9x 9x   1x 6x 6x   1x 1x 1x 1x   1x 14x 14x   1x 7x 7x 7x   1x   1x 1x 1x 19x 19x 19x 19x   1x 5x 5x  
// lib/reflection/memory.ts
 
import type { ReflectionMemoryEntry, ReflectionSnapshot } from './types';
 
// ========================================
//   Configuration
// ========================================
 
const MEMORY_CAPACITY = 100; // Maximum number of entries to keep in memory
 
// ========================================
//   Module State
// ========================================
 
const memoryBuffer: ReflectionMemoryEntry[] = [];
let currentSequence = 0;
let head = 0; // Pointer to the next slot to write to
 
// ========================================
//   Public API
// ========================================
 
/**
 * Adds a new entry to the reflection memory.
 * Overwrites the oldest entry if capacity is reached.
 * @param entry The partial memory entry to add.
 */
export function addToMemory(entry: Omit<ReflectionMemoryEntry, 'sequence' | 'timestamp'>): void {
  const newEntry: ReflectionMemoryEntry = {
    ...entry,
    sequence: ++currentSequence,
    timestamp: performance.now(),
  };
 
  memoryBuffer[head] = newEntry;
  head = (head + 1) % MEMORY_CAPACITY;
}
 
/**
 * Returns a copy of all entries currently in the reflection memory.
 * The entries are not guaranteed to be in chronological order.
 * @returns An array of memory entries.
 */
export function getMemorySnapshot(): Readonly<ReflectionMemoryEntry[]> {
  return [...memoryBuffer];
}
 
/**
 * Returns the most recent `n` entries from memory, ordered from newest to oldest.
 * @param count The number of recent entries to retrieve.
 * @returns An array of the most recent memory entries.
 */
export function getRecentMemory(count: number): Readonly<ReflectionMemoryEntry[]> {
  const snapshot = [...memoryBuffer];
  // Sort by sequence number in descending order to get the newest first
  snapshot.sort((a, b) => b.sequence - a.sequence);
  return snapshot.slice(0, count);
}
 
/**
 * Resets the reflection memory to its initial state.
 * (For testing purposes)
 */
export function _resetMemory(): void {
  memoryBuffer.length = 0;
  currentSequence = 0;
  head = 0;
}
 
// ------------------------------------------------------------------
// Backwards compatible API expected by tests
// ------------------------------------------------------------------
 
const snapshotBuffer: ReflectionSnapshot[] = [];
 
export function storeReflectionSnapshot(snapshot: ReflectionSnapshot): void {
  snapshotBuffer.push(snapshot);
}
 
export function getReflectionHistory(): ReflectionSnapshot[] {
  return [...snapshotBuffer].sort((a, b) => a.timestamp - b.timestamp);
}
 
export function getLastReflection(): ReflectionSnapshot | null {
  if (snapshotBuffer.length === 0) return null;
  return snapshotBuffer[snapshotBuffer.length - 1];
}
 
export function clearReflectionMemory(): void {
  snapshotBuffer.length = 0;
}
 
export function _resetMemoryForTests(): void {
  _resetMemory();
  clearReflectionMemory();
}
 
/**
 * Tests expect introspection to expose a "latest signals" buffer.
 */
const latestSignals: any[] = [];
export function _pushLatestSignals(signals: any[]) {
  latestSignals.push(...signals);
  // keep small
  if (latestSignals.length > 100) latestSignals.splice(0, latestSignals.length - 100);
}
 
export function getLatestSignals(): any[] {
  return [...latestSignals];
}