@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
111 lines (110 loc) • 4.78 kB
TypeScript
/**
* Conversation Memory Manager for NeuroLink
* Handles in-memory conversation storage, session management, and context injection
*/
import type { ChatMessage, ConversationMemoryConfig, ConversationMemoryStats, SessionListItem, SessionMemory, StoreConversationTurnOptions, IConversationMemoryManager } from "../types/index.js";
export declare class ConversationMemoryManager implements IConversationMemoryManager {
private sessions;
config: ConversationMemoryConfig;
private isInitialized;
private summarizationEngine;
/**
* Track sessions currently being summarized to prevent race conditions
*/
private summarizationInProgress;
constructor(config: ConversationMemoryConfig);
/**
* Initialize the memory manager
*/
initialize(): Promise<void>;
/** Whether this memory manager can persist data (always true for in-memory within process) */
get canPersist(): boolean;
/** Whether Redis client is configured (always false for in-memory) */
get isRedisConfigured(): boolean;
/** Get health status for monitoring */
getHealthStatus(): {
initialized: boolean;
connected: boolean;
};
/**
* Store a conversation turn for a session
* TOKEN-BASED: Validates message size and triggers summarization based on tokens
*/
storeConversationTurn(options: StoreConversationTurnOptions): Promise<void>;
/**
* Validate and prepare a message before adding to session
* Truncates if message exceeds token limit
*/
private validateAndPrepareMessage;
/**
* Check if summarization is needed based on token count
*/
private checkAndSummarize;
/**
* Estimate total tokens for a list of messages
*/
private estimateTokens;
/**
* Build context messages for AI prompt injection (TOKEN-BASED)
* Returns messages from pointer onwards (or all if no pointer)
* Now consistently async to match Redis implementation
*/
buildContextMessages(sessionId: string, _userId?: string, _enableSummarization?: boolean, requestId?: string): Promise<ChatMessage[]>;
getSession(sessionId: string, _userId?: string): SessionMemory | undefined;
createSummarySystemMessage(content: string, summarizesFrom?: string, summarizesTo?: string): ChatMessage;
private ensureInitialized;
private createNewSession;
private enforceSessionLimit;
getStats(): Promise<ConversationMemoryStats>;
/**
* List all sessions with metadata
* @param userId - Optional user ID 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;
clearSession(sessionId: string): Promise<boolean>;
clearAllSessions(): Promise<void>;
/**
* Get the raw messages array for a session.
* Returns the full messages list without context filtering or summarization.
* Returns a deep copy to prevent external mutation of internal state.
*/
getSessionMessages(sessionId: string, _userId?: string): Promise<ChatMessage[]>;
/**
* Replace the entire messages array for a session.
* Creates the session if it does not exist.
* Resets summary pointers since old pointers may reference messages that no longer exist.
*/
setSessionMessages(sessionId: string, messages: ChatMessage[], userId?: string): Promise<void>;
/**
* Persist a step's tool calls and results as `tool_call` / `tool_result`
* messages, mirroring the Redis manager.
*
* Parity fix: this used to exist only on the Redis backend, so an in-memory
* session never turned tool activity into messages and every downstream path
* that reasons about tool batches (compaction, pruning, pair repair) saw a
* different history shape depending on `STORAGE_TYPE`.
*
* Calls are written before results — the same order the Redis flush uses —
* and `toolCallId` is carried on BOTH sides so `repairToolPairs` can match by
* id rather than adjacency (a parallel batch has no positional pairing).
*/
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>;
/** Close/shutdown — no-op for in-memory manager (no external connections to release) */
close(): Promise<void>;
}