/** * Memory Hook Service * * Lightweight service for hooks to store/retrieve memory. * Direct SQLite access without HTTP worker. * * @module @agentkits/memory/hooks/service */ import { Observation, SessionRecord, UserPrompt, SessionSummary, MemoryContext, ContextConfig, MemorySettings, LifecycleConfig, LifecycleResult, LifecycleStats, ExportData, ImportResult } from './types.js'; /** * Memory Hook Service Configuration */ export interface MemoryHookServiceConfig { /** Base directory for memory storage */ baseDir: string; /** Database filename */ dbFilename: string; /** Maximum observations to return in context */ maxContextObservations: number; /** Maximum sessions to return in context */ maxContextSessions: number; /** Maximum response size to store (bytes) */ maxResponseSize: number; } /** * Memory Hook Service * * Provides direct SQLite access for hooks without HTTP overhead. * Stores observations and sessions for context injection. */ export declare class MemoryHookService { private config; private db; private initialized; private dbPath; constructor(cwd: string, config?: Partial); /** * Initialize the service */ initialize(): Promise; /** * Shutdown the service */ shutdown(): Promise; /** * Initialize or get session (idempotent) */ initSession(sessionId: string, project: string, prompt?: string): Promise; /** * Save a user prompt (tracks ALL prompts, not just the first) */ saveUserPrompt(sessionId: string, project: string, promptText: string): Promise; /** * Get the latest prompt text for a session (for intent detection) */ getLatestPromptText(sessionId: string): string | null; /** * Get current prompt number for a session (0 if no prompts yet) */ getPromptNumber(sessionId: string): number; /** * Get all prompts for a session */ getSessionPrompts(sessionId: string): Promise; /** * Get recent prompts across all sessions for a project */ getRecentPrompts(project: string, limit?: number): Promise; /** * Get session by ID */ getSession(sessionId: string): SessionRecord | null; /** * Complete a session with summary */ completeSession(sessionId: string, summary?: string): Promise; /** * Get recent sessions */ getRecentSessions(project: string, limit?: number): Promise; /** * Store an observation */ storeObservation(sessionId: string, project: string, toolName: string, toolInput: unknown, toolResponse: unknown, cwd: string): Promise; /** * Enrich an existing observation with AI-generated data. * Called from a background process after the observation is saved. * Updates subtitle, narrative, facts, and concepts in-place. */ enrichObservation(id: string): Promise; /** * Compress a single observation using AI. * Replaces raw tool_input/tool_response with a dense compressed_summary. * Sets is_compressed=1 to indicate the raw data has been replaced. */ compressObservation(id: string): Promise; /** * Compress all observations for a session and generate a session digest. * 1. Compresses each observation individually (10:1-25:1 ratio) * 2. Generates a session-level digest from summaries (20:1-100:1 ratio) * 3. Stores digest in session_digests table with embedding queued */ compressSessionObservations(sessionId: string): Promise<{ compressed: number; digestCreated: boolean; }>; /** * Build embedding text for a session record based on table type. */ private getSessionEmbeddingText; /** Max records to process per worker invocation */ private static readonly WORKER_BATCH_LIMIT; /** Max retries before marking a task as permanently failed */ private static readonly MAX_TASK_RETRIES; /** * Queue a background task. Inserts into SQLite task_queue — atomic, <1ms. * Called from hook handlers — non-blocking, no model/API loading. */ queueTask(taskType: 'embed' | 'enrich' | 'compress', table: string, recordId: string | number): void; /** * Spawn a detached background worker if not already running. * Uses a PID-based lock file to prevent multiple concurrent workers. * @param workerType - 'embed-session' or 'enrich-session' * @param lockName - unique lock file name for this worker type */ ensureWorkerRunning(cwd: string, workerType: string, lockName: string): void; /** * Process embedding tasks from the queue. * Loads embedding model ONCE, processes queued items + DB catch-up. * Uses lock file to prevent concurrent workers. */ processEmbeddingQueue(): Promise; /** * Process enrichment tasks from the queue. * Calls claude --print sequentially for each observation. * Uses lock file to prevent concurrent workers. */ processEnrichmentQueue(): Promise; /** * Process compression tasks from the queue. * Compresses observations and generates session digests. * Uses lock file to prevent concurrent workers. */ processCompressionQueue(): Promise; /** * Check if there are pending embedding tasks or records missing embeddings. * Used to decide whether to spawn the embed worker on session start. */ hasPendingEmbeddings(): boolean; /** * Check if there are pending enrichment tasks in the queue */ hasPendingEnrichments(): boolean; /** * Check if there are pending compression tasks in the queue */ hasPendingCompressions(): boolean; /** * Get observations for a session */ getSessionObservations(sessionId: string, limit?: number): Promise; /** * Get recent observations for a project */ getRecentObservations(project: string, limit?: number): Promise; /** * Load persistent settings from .claude/memory/settings.json * Returns merged with defaults (missing keys get default values) */ loadSettings(): MemorySettings; /** * Save settings to .claude/memory/settings.json */ saveSettings(settings: MemorySettings): void; /** * Get memory context for session start */ getContext(project: string, configOverride?: ContextConfig): Promise; /** * Format context as markdown */ private formatContextMarkdown; /** * Generate session summary from observations (legacy text format) */ generateSummary(sessionId: string): Promise; /** * Generate structured session summary from observations + prompts */ generateStructuredSummary(sessionId: string): Promise>; /** * Save structured session summary to session_summaries table */ saveSessionSummary(summary: Omit): Promise; /** * Get recent session summaries for a project */ getRecentSummaries(project: string, limit?: number): Promise; /** * Enrich a session summary with AI using transcript data. * Called from a background process after the template summary is saved. * Reads the transcript JSONL, extracts last assistant message, * then uses AI to enhance the completed/nextSteps fields. */ enrichSessionSummary(sessionId: string, transcriptPath: string): Promise; private rowToSummary; /** * Run lifecycle tasks: compress old observations, archive old sessions, * optionally delete archived sessions, and vacuum. */ runLifecycleTasks(config?: Partial): Promise; /** * Get lifecycle statistics for the database */ getLifecycleStats(): Promise; /** * Detect recurring patterns across sessions for a project. * Analyzes concept frequency across recent observations to identify * common workflows, frequently modified files, and recurring intents. * Returns top patterns sorted by frequency. */ detectCrossSessionPatterns(project: string, limit?: number): Promise>; /** * Export sessions and related data to JSON format */ exportToJSON(project: string, sessionIds?: string[]): Promise; /** * Import sessions and related data from JSON format. * Generates new session IDs prefixed with 'imported_' to avoid conflicts. * Deduplicates observations and prompts via content_hash. */ importFromJSON(data: ExportData): Promise; private ensureInitialized; private createSchema; /** * Migrate schema for existing databases (add new columns) */ private migrateSchema; private rowToSession; private rowToObservation; private formatRelativeTime; private formatIntentBadge; private getObservationIcon; } /** * Create a hook service for the given project directory */ export declare function createHookService(cwd: string): MemoryHookService; /** * Extract the last assistant message from a Claude Code transcript JSONL file. * Reads the file, iterates lines in reverse, finds the last 'assistant' type entry, * extracts text content, and strips tags. */ export declare function extractLastAssistantMessage(transcriptPath: string): string | null; export default MemoryHookService; //# sourceMappingURL=service.d.ts.map