@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
236 lines (235 loc) • 9.65 kB
TypeScript
/**
* Redis Conversation Memory Manager for NeuroLink
* Redis-based implementation of conversation storage with same interface as ConversationMemoryManager
*/
import type { ChatMessage, ConversationMemoryConfig, ConversationMemoryStats, RedisConversationObject, RedisStorageConfig, SessionListItem, SessionMemory, SessionMetadata, StoreConversationTurnOptions, AgenticLoopReportMetadata, IConversationMemoryManager } from "../types/index.js";
/**
* Redis-based implementation of the ConversationMemoryManager
* Uses the same interface but stores data in Redis
*/
export declare class RedisConversationMemoryManager implements IConversationMemoryManager {
config: ConversationMemoryConfig;
private isInitialized;
private summarizationEngine;
private redisConfig;
private redisClient;
/**
* Temporary storage for tool execution data to prevent race conditions
* Key format: "${sessionId}:${userId}"
*/
private pendingToolExecutions;
/**
* Track sessions currently generating titles to prevent race conditions
* Key format: "${sessionId}:${userId}"
*/
private titleGenerationInProgress;
/**
* Track sessions currently being summarized to prevent race conditions
* Key format: "${sessionId}:${userId}"
*/
private summarizationInProgress;
constructor(config: ConversationMemoryConfig, redisConfig?: RedisStorageConfig);
/**
* Initialize the memory manager with Redis connection
*/
initialize(): Promise<void>;
/** Whether this memory manager can persist data (Redis connected and initialized) */
get canPersist(): boolean;
/** Whether Redis client is configured and connected */
get isRedisConfigured(): boolean;
/** Get health status for monitoring */
getHealthStatus(): {
initialized: boolean;
connected: boolean;
host: string;
keyPrefix: string;
};
/**
* Get session by ID, reconstructing a SessionMemory from Redis storage.
*/
getSession(sessionId: string, userId?: string, requestId?: string): Promise<SessionMemory | undefined>;
/**
* Get raw session data without any filtering or transformation.
* Used by the memory retrieval tool and internal APIs that need
* access to full message data including unmodified tool outputs.
*/
getSessionRaw(sessionId: string, userId?: string): Promise<RedisConversationObject | null>;
/**
* Get all sessions for a specific user
*/
getUserSessions(userId: string): Promise<string[]>;
/**
* Add a session to user's session set (private method)
*/
private addUserSession;
/**
* Remove a session from user's session set (private method)
*/
private removeUserSession;
/**
* Generate current timestamp in ISO format
*/
private generateTimestamp;
/**
* Store tool execution data for a session (temporarily to avoid race conditions)
*/
storeToolExecution(sessionId: string, userId: string | undefined, toolCalls: Array<{
toolCallId?: string;
toolName?: string;
args?: Record<string, unknown>;
[key: string]: unknown;
}>, toolResults: Array<{
toolCallId?: string;
output?: unknown;
result?: unknown;
error?: string;
[key: string]: unknown;
}>, currentTime?: Date): Promise<void>;
/**
* Store a conversation turn for a session
*/
storeConversationTurn(options: StoreConversationTurnOptions): Promise<void>;
/**
* Check if summarization is needed based on token count
*/
private checkAndSummarize;
/**
* True only for keys holding a conversation BLOB — the sole key type these
* scan-then-GET paths may read.
*
* `${keyPrefix}*` also matches the companion message LISTs and, when a
* custom key prefix does not end in `conversation:`, the user-index SETs
* (whose derived prefix then collapses onto `keyPrefix`). `GET` against
* either raises WRONGTYPE, and counting them would inflate session totals.
*/
private isConversationBlobKey;
/**
* Hydrate a deserialized blob's messages from the companion LIST when the
* session uses split storage. Legacy blobs (messages inline) pass through
* untouched — that is what makes the migration backward compatible.
*/
private hydrateMessages;
/** Message count without materializing them — LLEN for split sessions. */
private countMessages;
/** Load a session, messages included, regardless of storage format. */
private loadConversation;
/**
* Persist a conversation, splitting messages into the companion LIST.
* `appendFrom` appends only messages from that index onward (the per-turn
* fast path); omit it to rewrite the LIST wholesale, which is also how a
* legacy blob gets converted.
*/
private persistConversation;
/**
* Build context messages for AI prompt injection (TOKEN-BASED)
* Returns messages from pointer onwards (or all if no pointer)
* Applies sendToolPreview toggle and hydrates result.result for backward compat
*/
buildContextMessages(sessionId: string, userId?: string, enableSummarization?: boolean, requestId?: string): Promise<ChatMessage[]>;
/**
* Get session metadata for a specific user session (optimized for listing)
* Fetches only essential metadata without heavy message arrays
*
* @param userId The user identifier
* @param sessionId The session identifier
* @returns Session metadata or null if session doesn't exist
*/
getUserSessionMetadata(userId: string, sessionId: string): Promise<SessionMetadata | null>;
/**
* Get conversation history for a specific user session
*
* @param userId The user identifier
* @param sessionId The session identifier
* @returns Array of chat messages or null if session doesn't exist
*/
getUserSessionHistory(userId: string, sessionId: string): Promise<ChatMessage[] | null>;
/**
* Get the complete conversation object for a specific user session
*
* This method returns the full conversation object including title, metadata,
* timestamps, and all chat messages. Unlike getUserSessionHistory() which returns
* only the messages array, this method provides the complete conversation context.
*
* @param userId The user identifier who owns the session
* @param sessionId The unique session identifier
* @returns Complete conversation object with all data, or null if session doesn't exist
*/
getUserSessionObject(userId: string, sessionId: string): Promise<RedisConversationObject | null>;
/**
* Generate a conversation title from the first user message
* Uses AI to create a concise, descriptive title (5-8 words)
*/
generateConversationTitle(userMessage: string): Promise<string>;
/**
* Create summary system message
*/
createSummarySystemMessage(content: string, summarizesFrom?: string, summarizesTo?: string): ChatMessage;
/**
* Get the raw messages array for a session.
* Returns the full messages list without context filtering or summarization.
*/
getSessionMessages(sessionId: string, userId?: string): Promise<ChatMessage[]>;
/**
* Replace the entire messages array for a session.
* The session must already exist in Redis.
*/
setSessionMessages(sessionId: string, messages: ChatMessage[], userId?: string): Promise<void>;
/**
* Close Redis connection
*/
close(): Promise<void>;
/**
* Get statistics about conversation storage
*/
getStats(): Promise<ConversationMemoryStats>;
/**
* Clear a specific session
*/
clearSession(sessionId: string, userId?: string): Promise<boolean>;
/**
* Clear all sessions
*/
clearAllSessions(): Promise<void>;
/**
* Ensure Redis client is initialized
*/
private ensureInitialized;
/**
* Get session metadata for all sessions of a user (optimized for listing)
* Returns only essential metadata without heavy message arrays
*
* @param userId The user identifier
* @returns Array of session metadata objects
*/
getUserAllSessionsHistory(userId: string): Promise<SessionMetadata[]>;
/**
* List all sessions with metadata for CLI/API usage
* Implements IConversationMemoryManager.listSessions
* @param userId - Optional user identifier to filter sessions
* @returns Array of session list items with metadata
*/
listSessions(userId?: string): Promise<SessionListItem[]>;
/**
* Format milliseconds into human-readable time ago string
*/
private formatTimeAgo;
/**
* Clean up stale pending tool execution data
* Removes data older than 5 minutes to prevent memory leaks
*/
private cleanupStalePendingData;
/**
* Flush pending tool execution data for a session and merge into conversation
*/
private flushPendingToolData;
/**
* Update agentic loop report metadata for a conversation session.
* Upserts a report entry by reportId — updates existing or adds new.
* Follows the read → patch → write pattern (same as title generation).
*
* @param sessionId The session identifier
* @param userId The user identifier (optional)
* @param report The report metadata to upsert
*/
updateAgenticLoopReport(sessionId: string, userId: string | undefined, report: AgenticLoopReportMetadata): Promise<void>;
}