@juspay/neurolink 7.11.1 → 7.13.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +16 -0
  3. package/dist/config/conversationMemoryConfig.d.ts +27 -0
  4. package/dist/config/conversationMemoryConfig.js +39 -0
  5. package/dist/context/ContextManager.d.ts +28 -0
  6. package/dist/context/ContextManager.js +102 -0
  7. package/dist/context/config.d.ts +5 -0
  8. package/dist/context/config.js +38 -0
  9. package/dist/context/types.d.ts +20 -0
  10. package/dist/context/types.js +1 -0
  11. package/dist/context/utils.d.ts +7 -0
  12. package/dist/context/utils.js +8 -0
  13. package/dist/core/baseProvider.js +4 -2
  14. package/dist/core/conversationMemoryManager.d.ts +41 -0
  15. package/dist/core/conversationMemoryManager.js +152 -0
  16. package/dist/core/types.d.ts +2 -0
  17. package/dist/lib/config/conversationMemoryConfig.d.ts +27 -0
  18. package/dist/lib/config/conversationMemoryConfig.js +39 -0
  19. package/dist/lib/context/ContextManager.d.ts +28 -0
  20. package/dist/lib/context/ContextManager.js +102 -0
  21. package/dist/lib/context/config.d.ts +5 -0
  22. package/dist/lib/context/config.js +38 -0
  23. package/dist/lib/context/types.d.ts +20 -0
  24. package/dist/lib/context/types.js +1 -0
  25. package/dist/lib/context/utils.d.ts +7 -0
  26. package/dist/lib/context/utils.js +8 -0
  27. package/dist/lib/core/baseProvider.js +4 -2
  28. package/dist/lib/core/conversationMemoryManager.d.ts +41 -0
  29. package/dist/lib/core/conversationMemoryManager.js +152 -0
  30. package/dist/lib/core/types.d.ts +2 -0
  31. package/dist/lib/neurolink.d.ts +39 -4
  32. package/dist/lib/neurolink.js +106 -5
  33. package/dist/lib/providers/amazonBedrock.js +4 -2
  34. package/dist/lib/providers/anthropic.js +4 -2
  35. package/dist/lib/providers/azureOpenai.js +4 -2
  36. package/dist/lib/providers/googleAiStudio.js +4 -2
  37. package/dist/lib/providers/googleVertex.js +4 -2
  38. package/dist/lib/providers/huggingFace.js +4 -2
  39. package/dist/lib/providers/litellm.js +4 -2
  40. package/dist/lib/providers/mistral.js +3 -2
  41. package/dist/lib/providers/openAI.js +4 -2
  42. package/dist/lib/types/conversationTypes.d.ts +95 -0
  43. package/dist/lib/types/conversationTypes.js +17 -0
  44. package/dist/lib/types/streamTypes.d.ts +2 -0
  45. package/dist/lib/utils/conversationMemoryUtils.d.ts +22 -0
  46. package/dist/lib/utils/conversationMemoryUtils.js +77 -0
  47. package/dist/lib/utils/messageBuilder.d.ts +13 -0
  48. package/dist/lib/utils/messageBuilder.js +48 -0
  49. package/dist/neurolink.d.ts +39 -4
  50. package/dist/neurolink.js +106 -5
  51. package/dist/providers/amazonBedrock.js +4 -2
  52. package/dist/providers/anthropic.js +4 -2
  53. package/dist/providers/azureOpenai.js +4 -2
  54. package/dist/providers/googleAiStudio.js +4 -2
  55. package/dist/providers/googleVertex.js +4 -2
  56. package/dist/providers/huggingFace.js +4 -2
  57. package/dist/providers/litellm.js +4 -2
  58. package/dist/providers/mistral.js +3 -2
  59. package/dist/providers/openAI.js +4 -2
  60. package/dist/types/conversationTypes.d.ts +95 -0
  61. package/dist/types/conversationTypes.js +17 -0
  62. package/dist/types/streamTypes.d.ts +2 -0
  63. package/dist/utils/conversationMemoryUtils.d.ts +22 -0
  64. package/dist/utils/conversationMemoryUtils.js +77 -0
  65. package/dist/utils/messageBuilder.d.ts +13 -0
  66. package/dist/utils/messageBuilder.js +48 -0
  67. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [7.13.0](https://github.com/juspay/neurolink/compare/v7.12.0...v7.13.0) (2025-08-14)
2
+
3
+ ### Features
4
+
5
+ - **(SDK):** Add context summarizer for conversation BZ-43204 ([38231c4](https://github.com/juspay/neurolink/commit/38231c475b7546c16db741010173794251a7dbaa))
6
+
7
+ ## [7.12.0](https://github.com/juspay/neurolink/compare/v7.11.1...v7.12.0) (2025-08-14)
8
+
9
+ ### Features
10
+
11
+ - **(memory):** Added support for Conversation History ([5cf3650](https://github.com/juspay/neurolink/commit/5cf36507ec12fca525df652c1c15acc8c1c71297))
12
+
1
13
  ## [7.11.1](https://github.com/juspay/neurolink/compare/v7.11.0...v7.11.1) (2025-08-14)
2
14
 
3
15
  ### Bug Fixes
package/README.md CHANGED
@@ -162,6 +162,21 @@ console.log(result.content);
162
162
  console.log(`Used: ${result.provider}`);
163
163
  ```
164
164
 
165
+ ### Conversation Memory
166
+
167
+ NeuroLink supports automatic conversation history management that maintains context across multiple turns within sessions. This enables AI to remember previous interactions and provide contextually aware responses. Session-based memory isolation ensures privacy between different conversations.
168
+
169
+ ```typescript
170
+ // Enable conversation memory with configurable limits
171
+ const neurolink = new NeuroLink({
172
+ conversationMemory: {
173
+ enabled: true,
174
+ maxSessions: 50, // Keep last 50 sessions
175
+ maxTurnsPerSession: 20, // Keep last 20 turns per session
176
+ },
177
+ });
178
+ ```
179
+
165
180
  #### 🔗 CLI-SDK Consistency (NEW! ✨)
166
181
 
167
182
  Method aliases that match CLI command names:
@@ -316,6 +331,7 @@ console.log(productData.name, productData.price, productData.features);
316
331
  - 🔍 **Smart Model Resolution** - Fuzzy matching, aliases, and capability-based search across all providers
317
332
  - 🏠 **Local AI Support** - Run completely offline with Ollama or through LiteLLM proxy
318
333
  - 🌍 **Universal Model Access** - Direct providers + 100,000+ models via Hugging Face + 100+ models via LiteLLM
334
+ - 🧠 **Automatic Context Summarization** - Stateful, long-running conversations with automatic history summarization.
319
335
  - 📊 **Analytics & Evaluation** - Built-in usage tracking and AI-powered quality assessment
320
336
 
321
337
  ## 🛠️ MCP Integration Status ✅ **BUILT-IN TOOLS WORKING**
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Conversation Memory Configuration
3
+ * Provides default values for conversation memory feature with environment variable support
4
+ */
5
+ import type { ConversationMemoryConfig } from "../types/conversationTypes.js";
6
+ /**
7
+ * Default maximum number of turns per session
8
+ */
9
+ export declare const DEFAULT_MAX_TURNS_PER_SESSION = 50;
10
+ /**
11
+ * Default maximum number of sessions
12
+ */
13
+ export declare const DEFAULT_MAX_SESSIONS = 50;
14
+ /**
15
+ * Number of messages per conversation turn (user + assistant)
16
+ */
17
+ export declare const MESSAGES_PER_TURN = 2;
18
+ /**
19
+ * Conversation instructions for ongoing conversations
20
+ * Used to enhance system prompts when conversation history exists
21
+ */
22
+ export declare const CONVERSATION_INSTRUCTIONS = "\n\nIMPORTANT: You are continuing an ongoing conversation. The previous messages in this conversation contain important context including:\n- Names, personal information, and preferences shared by the user\n- Projects, tasks, and topics discussed previously \n- Any decisions, agreements, or conclusions reached\n\nAlways reference and build upon this conversation history when relevant. If the user asks about information mentioned earlier in the conversation, refer to those previous messages to provide accurate, contextual responses.";
23
+ /**
24
+ * Get default configuration values for conversation memory
25
+ * Reads environment variables when called (not at module load time)
26
+ */
27
+ export declare function getConversationMemoryDefaults(): ConversationMemoryConfig;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Conversation Memory Configuration
3
+ * Provides default values for conversation memory feature with environment variable support
4
+ */
5
+ /**
6
+ * Default maximum number of turns per session
7
+ */
8
+ export const DEFAULT_MAX_TURNS_PER_SESSION = 50;
9
+ /**
10
+ * Default maximum number of sessions
11
+ */
12
+ export const DEFAULT_MAX_SESSIONS = 50;
13
+ /**
14
+ * Number of messages per conversation turn (user + assistant)
15
+ */
16
+ export const MESSAGES_PER_TURN = 2;
17
+ /**
18
+ * Conversation instructions for ongoing conversations
19
+ * Used to enhance system prompts when conversation history exists
20
+ */
21
+ export const CONVERSATION_INSTRUCTIONS = `
22
+
23
+ IMPORTANT: You are continuing an ongoing conversation. The previous messages in this conversation contain important context including:
24
+ - Names, personal information, and preferences shared by the user
25
+ - Projects, tasks, and topics discussed previously
26
+ - Any decisions, agreements, or conclusions reached
27
+
28
+ Always reference and build upon this conversation history when relevant. If the user asks about information mentioned earlier in the conversation, refer to those previous messages to provide accurate, contextual responses.`;
29
+ /**
30
+ * Get default configuration values for conversation memory
31
+ * Reads environment variables when called (not at module load time)
32
+ */
33
+ export function getConversationMemoryDefaults() {
34
+ return {
35
+ enabled: process.env.NEUROLINK_MEMORY_ENABLED === "true",
36
+ maxSessions: Number(process.env.NEUROLINK_MEMORY_MAX_SESSIONS) || DEFAULT_MAX_SESSIONS,
37
+ maxTurnsPerSession: Number(process.env.NEUROLINK_MEMORY_MAX_TURNS_PER_SESSION) || DEFAULT_MAX_TURNS_PER_SESSION,
38
+ };
39
+ }
@@ -0,0 +1,28 @@
1
+ import type { TextGenerationOptions, TextGenerationResult } from "../core/types.js";
2
+ import type { ContextManagerConfig } from "./types.js";
3
+ type InternalGenerator = (options: TextGenerationOptions) => Promise<TextGenerationResult>;
4
+ /**
5
+ * Manages conversation context, automatically summarizing it when it
6
+ * exceeds a specified word count limit.
7
+ */
8
+ export declare class ContextManager {
9
+ private static readonly SUMMARIZATION_FAILED_WARNING;
10
+ private static readonly SUMMARIZATION_EMPTY_WARNING;
11
+ private history;
12
+ private wordCount;
13
+ private readonly internalGenerator;
14
+ private readonly config;
15
+ constructor(generatorFunction: InternalGenerator, config: ContextManagerConfig, initialContext?: string);
16
+ addTurn(role: "user" | "assistant", message: string): Promise<void>;
17
+ /**
18
+ * Formats the history including the latest user turn for the prompt, without modifying the permanent history.
19
+ */
20
+ getContextForPrompt(role: "user", message: string): string;
21
+ getCurrentContext(): string;
22
+ private _summarize;
23
+ /**
24
+ * Truncates the history to a specific word count, preserving the most recent messages.
25
+ */
26
+ private _truncateHistory;
27
+ }
28
+ export {};
@@ -0,0 +1,102 @@
1
+ import { logger } from "../utils/logger.js";
2
+ import { formatHistoryToString } from "./utils.js";
3
+ /**
4
+ * Manages conversation context, automatically summarizing it when it
5
+ * exceeds a specified word count limit.
6
+ */
7
+ export class ContextManager {
8
+ static SUMMARIZATION_FAILED_WARNING = "[System Warning: Context summarization failed. Conversation history has been truncated.]";
9
+ static SUMMARIZATION_EMPTY_WARNING = "[System Warning: Context summarization failed to return valid content. Conversation history has been truncated.]";
10
+ history;
11
+ wordCount;
12
+ internalGenerator;
13
+ config;
14
+ constructor(generatorFunction, config, initialContext = "This is the start of the conversation.") {
15
+ this.internalGenerator = generatorFunction;
16
+ this.config = config;
17
+ const initialMessage = { role: "system", content: initialContext };
18
+ initialMessage.wordCount = this.config.estimateWordCount([initialMessage]);
19
+ this.history = [initialMessage];
20
+ this.wordCount = initialMessage.wordCount;
21
+ }
22
+ async addTurn(role, message) {
23
+ const newMessage = { role, content: message };
24
+ newMessage.wordCount = this.config.estimateWordCount([newMessage]);
25
+ this.history.push(newMessage);
26
+ this.wordCount += newMessage.wordCount;
27
+ logger.info(`[ContextManager] Current word count: ${this.wordCount} / ${this.config.highWaterMarkWords}`);
28
+ if (this.wordCount > this.config.highWaterMarkWords) {
29
+ await this._summarize();
30
+ }
31
+ }
32
+ /**
33
+ * Formats the history including the latest user turn for the prompt, without modifying the permanent history.
34
+ */
35
+ getContextForPrompt(role, message) {
36
+ const tempHistory = [...this.history, { role, content: message }];
37
+ return formatHistoryToString(tempHistory);
38
+ }
39
+ getCurrentContext() {
40
+ // Format the history into a single string for the provider prompt
41
+ return formatHistoryToString(this.history);
42
+ }
43
+ async _summarize() {
44
+ try {
45
+ const prompt = this.config.getSummarizationPrompt(this.history, this.config.lowWaterMarkWords);
46
+ // Construct options for the internal method, bypassing the main 'generate' entry point
47
+ const textOptions = {
48
+ prompt,
49
+ provider: this.config.summarizationProvider,
50
+ model: this.config.summarizationModel,
51
+ // Ensure summarization does not trigger more context management or tools
52
+ disableTools: true,
53
+ };
54
+ // Call the internal generation function directly to avoid recursion
55
+ const result = await this.internalGenerator(textOptions);
56
+ if (typeof result.content === "string" && result.content.length > 0) {
57
+ // Replace the history with a single system message containing the summary
58
+ const newHistory = [{ role: "system", content: result.content }];
59
+ this.history = newHistory;
60
+ this.wordCount = this.config.estimateWordCount(this.history);
61
+ logger.info(`[ContextManager] Summarization complete. New history length: ${this.wordCount} words.`);
62
+ }
63
+ else {
64
+ logger.warn("[ContextManager] Summarization returned empty or non-string content; truncating history as a fallback.");
65
+ this._truncateHistory(this.config.lowWaterMarkWords);
66
+ this.history.unshift({ role: "system", content: ContextManager.SUMMARIZATION_EMPTY_WARNING });
67
+ this.wordCount = this.config.estimateWordCount(this.history);
68
+ }
69
+ logger.debug(`[ContextManager] New history: ${JSON.stringify(this.history)}`);
70
+ }
71
+ catch (error) {
72
+ logger.error("Context summarization failed:", { error });
73
+ // Fallback strategy: truncate the history to the target word count.
74
+ this._truncateHistory(this.config.lowWaterMarkWords);
75
+ this.history.unshift({ role: "system", content: ContextManager.SUMMARIZATION_FAILED_WARNING });
76
+ this.wordCount = this.config.estimateWordCount(this.history);
77
+ }
78
+ }
79
+ /**
80
+ * Truncates the history to a specific word count, preserving the most recent messages.
81
+ */
82
+ _truncateHistory(wordLimit) {
83
+ if (this.wordCount <= wordLimit) {
84
+ return;
85
+ }
86
+ let runningCount = 0;
87
+ let sliceIndex = this.history.length;
88
+ for (let i = this.history.length - 1; i >= 0; i--) {
89
+ let wordCount = this.history[i].wordCount;
90
+ if (wordCount === undefined) {
91
+ logger.warn(`[ContextManager] Word count cache missing for message at index ${i}. Recalculating.`);
92
+ wordCount = this.config.estimateWordCount([this.history[i]]);
93
+ }
94
+ runningCount += wordCount;
95
+ if (runningCount > wordLimit) {
96
+ sliceIndex = i + 1;
97
+ break;
98
+ }
99
+ }
100
+ this.history = this.history.slice(sliceIndex);
101
+ }
102
+ }
@@ -0,0 +1,5 @@
1
+ import type { ContextManagerConfig } from "./types.js";
2
+ /**
3
+ * Default configuration for the ContextManager.
4
+ */
5
+ export declare const defaultContextConfig: ContextManagerConfig;
@@ -0,0 +1,38 @@
1
+ import { formatHistoryToString } from "./utils.js";
2
+ /**
3
+ * Estimates the word count of a conversation history.
4
+ */
5
+ function estimateWordCount(history) {
6
+ if (!history || history.length === 0) {
7
+ return 0;
8
+ }
9
+ return history.reduce((acc, msg) => acc + (msg.content.trim().split(/\s+/).filter(word => word.length > 0).length || 0), 0);
10
+ }
11
+ /**
12
+ * Generates the default prompt for summarization.
13
+ */
14
+ function getDefaultSummarizationPrompt(history, wordLimit) {
15
+ const formattedHistory = formatHistoryToString(history);
16
+ return `
17
+ You are a context summarization AI. Your task is to condense the following conversation history for another AI assistant.
18
+ The summary must be a concise, third-person narrative that retains all critical information. Pay special attention to retaining key entities, technical details, decisions made, and any specific dates or times mentioned.
19
+ Ensure the summary flows logically and is ready to be used as context for the next turn in the conversation.
20
+ Please keep the summary under ${wordLimit} words.
21
+
22
+ Conversation History to Summarize:
23
+ ---
24
+ ${formattedHistory}
25
+ ---
26
+ `.trim();
27
+ }
28
+ /**
29
+ * Default configuration for the ContextManager.
30
+ */
31
+ export const defaultContextConfig = {
32
+ highWaterMarkWords: 3000,
33
+ lowWaterMarkWords: 800,
34
+ summarizationModel: "gemini-2.5-flash",
35
+ summarizationProvider: "googlevertex",
36
+ getSummarizationPrompt: getDefaultSummarizationPrompt,
37
+ estimateWordCount: estimateWordCount,
38
+ };
@@ -0,0 +1,20 @@
1
+ export interface ChatMessage {
2
+ /** Role of the message sender */
3
+ role: "user" | "assistant" | "system";
4
+ /** Content of the message */
5
+ content: string;
6
+ /** Cached word count for performance */
7
+ wordCount?: number;
8
+ }
9
+ /**
10
+ * Defines the configuration for the ContextManager.
11
+ * This allows for easy customization of the summarization behavior.
12
+ */
13
+ export interface ContextManagerConfig {
14
+ highWaterMarkWords: number;
15
+ lowWaterMarkWords: number;
16
+ summarizationModel: string;
17
+ summarizationProvider: string;
18
+ getSummarizationPrompt: (history: ChatMessage[], wordLimit: number) => string;
19
+ estimateWordCount: (history: ChatMessage[]) => number;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { ChatMessage } from "./types.js";
2
+ /**
3
+ * Formats a chat history array into a single string for use in a prompt.
4
+ * @param history The array of ChatMessage objects.
5
+ * @returns A formatted string representing the conversation.
6
+ */
7
+ export declare function formatHistoryToString(history: ChatMessage[]): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formats a chat history array into a single string for use in a prompt.
3
+ * @param history The array of ChatMessage objects.
4
+ * @returns A formatted string representing the conversation.
5
+ */
6
+ export function formatHistoryToString(history) {
7
+ return history.map(msg => `${msg.role}: ${msg.content}`).join('\n\n');
8
+ }
@@ -4,6 +4,7 @@ import { directAgentTools } from "../agent/directTools.js";
4
4
  import { getSafeMaxTokens } from "../utils/tokenLimits.js";
5
5
  import { createTimeoutController, TimeoutError } from "../utils/timeout.js";
6
6
  import { shouldDisableBuiltinTools } from "../utils/toolUtils.js";
7
+ import { buildMessagesArray } from "../utils/messageBuilder.js";
7
8
  /**
8
9
  * Validates if a result contains a valid toolsObject structure
9
10
  * @param result - The result object to validate
@@ -162,10 +163,11 @@ export class BaseProvider {
162
163
  logger.debug(`[BaseProvider.generate] Tools for ${this.providerName}: ${Object.keys(tools).join(", ")}`);
163
164
  // EVERY provider uses Vercel AI SDK - no exceptions
164
165
  const model = await this.getAISDKModel(); // This method is now REQUIRED
166
+ // Build proper message array with conversation history
167
+ const messages = buildMessagesArray(options);
165
168
  const result = await generateText({
166
169
  model,
167
- prompt: options.prompt || options.input?.text || "",
168
- system: options.systemPrompt,
170
+ messages: messages,
169
171
  tools,
170
172
  maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
171
173
  toolChoice: shouldUseTools ? "auto" : "none",
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Conversation Memory Manager for NeuroLink
3
+ * Handles in-memory conversation storage, session management, and context injection
4
+ */
5
+ import type { ConversationMemoryConfig, ConversationMemoryStats, ChatMessage } from "../types/conversationTypes.js";
6
+ export declare class ConversationMemoryManager {
7
+ private sessions;
8
+ private config;
9
+ private isInitialized;
10
+ constructor(config: ConversationMemoryConfig);
11
+ /**
12
+ * Initialize the memory manager
13
+ */
14
+ initialize(): Promise<void>;
15
+ /**
16
+ * Store a conversation turn for a session
17
+ * ULTRA-OPTIMIZED: Direct ChatMessage[] storage with zero conversion overhead
18
+ */
19
+ storeConversationTurn(sessionId: string, userId: string | undefined, userMessage: string, aiResponse: string): Promise<void>;
20
+ /**
21
+ * Build context messages for AI prompt injection (ULTRA-OPTIMIZED)
22
+ * Returns pre-stored message array with zero conversion overhead
23
+ */
24
+ buildContextMessages(sessionId: string): ChatMessage[];
25
+ /**
26
+ * Get memory statistics (simplified for pure in-memory storage)
27
+ * ULTRA-OPTIMIZED: Calculate turns from message count (each turn = MESSAGES_PER_TURN messages)
28
+ */
29
+ getStats(): Promise<ConversationMemoryStats>;
30
+ /**
31
+ * Clear all conversations for a specific session
32
+ */
33
+ clearSession(sessionId: string): Promise<boolean>;
34
+ /**
35
+ * Clear all conversations (reset memory)
36
+ */
37
+ clearAllSessions(): Promise<void>;
38
+ private ensureInitialized;
39
+ private createNewSession;
40
+ private enforceSessionLimit;
41
+ }
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Conversation Memory Manager for NeuroLink
3
+ * Handles in-memory conversation storage, session management, and context injection
4
+ */
5
+ import { ConversationMemoryError } from "../types/conversationTypes.js";
6
+ import { DEFAULT_MAX_TURNS_PER_SESSION, DEFAULT_MAX_SESSIONS, MESSAGES_PER_TURN } from "../config/conversationMemoryConfig.js";
7
+ import { logger } from "../utils/logger.js";
8
+ export class ConversationMemoryManager {
9
+ sessions = new Map();
10
+ config;
11
+ isInitialized = false;
12
+ constructor(config) {
13
+ // Trust that config is already complete from applyConversationMemoryDefaults()
14
+ this.config = config;
15
+ }
16
+ /**
17
+ * Initialize the memory manager
18
+ */
19
+ async initialize() {
20
+ if (this.isInitialized) {
21
+ return;
22
+ }
23
+ try {
24
+ this.isInitialized = true;
25
+ logger.info("ConversationMemoryManager initialized", {
26
+ storage: "in-memory",
27
+ maxSessions: this.config.maxSessions,
28
+ maxTurnsPerSession: this.config.maxTurnsPerSession,
29
+ });
30
+ }
31
+ catch (error) {
32
+ throw new ConversationMemoryError("Failed to initialize conversation memory", "CONFIG_ERROR", { error: error instanceof Error ? error.message : String(error) });
33
+ }
34
+ }
35
+ /**
36
+ * Store a conversation turn for a session
37
+ * ULTRA-OPTIMIZED: Direct ChatMessage[] storage with zero conversion overhead
38
+ */
39
+ async storeConversationTurn(sessionId, userId, userMessage, aiResponse) {
40
+ await this.ensureInitialized();
41
+ try {
42
+ // Get or create session
43
+ let session = this.sessions.get(sessionId);
44
+ if (!session) {
45
+ session = this.createNewSession(sessionId, userId);
46
+ this.sessions.set(sessionId, session);
47
+ }
48
+ // ULTRA-OPTIMIZED: Direct message storage - no intermediate objects
49
+ session.messages.push({ role: "user", content: userMessage }, { role: "assistant", content: aiResponse });
50
+ session.lastActivity = Date.now();
51
+ // Enforce per-session turn limit (each turn = MESSAGES_PER_TURN messages: user + assistant)
52
+ const maxMessages = (this.config.maxTurnsPerSession || DEFAULT_MAX_TURNS_PER_SESSION) * MESSAGES_PER_TURN;
53
+ if (session.messages.length > maxMessages) {
54
+ session.messages = session.messages.slice(-maxMessages);
55
+ }
56
+ // Enforce global session limit
57
+ this.enforceSessionLimit();
58
+ logger.debug("Conversation turn stored", {
59
+ sessionId,
60
+ messageCount: session.messages.length,
61
+ turnCount: session.messages.length / MESSAGES_PER_TURN, // Each turn = MESSAGES_PER_TURN messages
62
+ userMessageLength: userMessage.length,
63
+ aiResponseLength: aiResponse.length,
64
+ });
65
+ }
66
+ catch (error) {
67
+ throw new ConversationMemoryError(`Failed to store conversation turn for session ${sessionId}`, "STORAGE_ERROR", {
68
+ sessionId,
69
+ error: error instanceof Error ? error.message : String(error),
70
+ });
71
+ }
72
+ }
73
+ /**
74
+ * Build context messages for AI prompt injection (ULTRA-OPTIMIZED)
75
+ * Returns pre-stored message array with zero conversion overhead
76
+ */
77
+ buildContextMessages(sessionId) {
78
+ const session = this.sessions.get(sessionId);
79
+ if (!session || session.messages.length === 0) {
80
+ return [];
81
+ }
82
+ // ULTRA-OPTIMIZED: Direct return - no processing needed!
83
+ return session.messages;
84
+ }
85
+ /**
86
+ * Get memory statistics (simplified for pure in-memory storage)
87
+ * ULTRA-OPTIMIZED: Calculate turns from message count (each turn = MESSAGES_PER_TURN messages)
88
+ */
89
+ async getStats() {
90
+ await this.ensureInitialized();
91
+ const sessions = Array.from(this.sessions.values());
92
+ const totalTurns = sessions.reduce((sum, session) => sum + session.messages.length / MESSAGES_PER_TURN, 0);
93
+ return {
94
+ totalSessions: sessions.length,
95
+ totalTurns,
96
+ };
97
+ }
98
+ /**
99
+ * Clear all conversations for a specific session
100
+ */
101
+ async clearSession(sessionId) {
102
+ const session = this.sessions.get(sessionId);
103
+ if (!session) {
104
+ return false;
105
+ }
106
+ // Remove from memory
107
+ this.sessions.delete(sessionId);
108
+ logger.info("Session cleared", { sessionId });
109
+ return true;
110
+ }
111
+ /**
112
+ * Clear all conversations (reset memory)
113
+ */
114
+ async clearAllSessions() {
115
+ const sessionIds = Array.from(this.sessions.keys());
116
+ // Clear memory
117
+ this.sessions.clear();
118
+ logger.info("All sessions cleared", { clearedCount: sessionIds.length });
119
+ }
120
+ // Private methods
121
+ async ensureInitialized() {
122
+ if (!this.isInitialized) {
123
+ await this.initialize();
124
+ }
125
+ }
126
+ createNewSession(sessionId, userId) {
127
+ return {
128
+ sessionId,
129
+ userId,
130
+ messages: [],
131
+ createdAt: Date.now(),
132
+ lastActivity: Date.now(),
133
+ };
134
+ }
135
+ enforceSessionLimit() {
136
+ const maxSessions = this.config.maxSessions || DEFAULT_MAX_SESSIONS;
137
+ if (this.sessions.size <= maxSessions) {
138
+ return;
139
+ }
140
+ // Sort sessions by last activity (oldest first)
141
+ const sessions = Array.from(this.sessions.entries()).sort(([, a], [, b]) => a.lastActivity - b.lastActivity);
142
+ // Remove oldest sessions
143
+ const sessionsToRemove = sessions.slice(0, sessions.length - maxSessions);
144
+ for (const [sessionId] of sessionsToRemove) {
145
+ this.sessions.delete(sessionId);
146
+ }
147
+ logger.debug("Session limit enforced", {
148
+ removedSessions: sessionsToRemove.length,
149
+ remainingSessions: this.sessions.size,
150
+ });
151
+ }
152
+ }
@@ -3,6 +3,7 @@ import type { Schema, Tool } from "ai";
3
3
  import type { GenerateResult } from "../types/generateTypes.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
5
5
  import type { JsonValue } from "../types/common.js";
6
+ import type { ChatMessage } from "../types/conversationTypes.js";
6
7
  export interface TextGenerationResult {
7
8
  content: string;
8
9
  provider?: string;
@@ -150,6 +151,7 @@ export interface TextGenerationOptions {
150
151
  role: string;
151
152
  content: string;
152
153
  }>;
154
+ conversationMessages?: ChatMessage[];
153
155
  }
154
156
  /**
155
157
  * Analytics data for usage tracking
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Conversation Memory Configuration
3
+ * Provides default values for conversation memory feature with environment variable support
4
+ */
5
+ import type { ConversationMemoryConfig } from "../types/conversationTypes.js";
6
+ /**
7
+ * Default maximum number of turns per session
8
+ */
9
+ export declare const DEFAULT_MAX_TURNS_PER_SESSION = 50;
10
+ /**
11
+ * Default maximum number of sessions
12
+ */
13
+ export declare const DEFAULT_MAX_SESSIONS = 50;
14
+ /**
15
+ * Number of messages per conversation turn (user + assistant)
16
+ */
17
+ export declare const MESSAGES_PER_TURN = 2;
18
+ /**
19
+ * Conversation instructions for ongoing conversations
20
+ * Used to enhance system prompts when conversation history exists
21
+ */
22
+ export declare const CONVERSATION_INSTRUCTIONS = "\n\nIMPORTANT: You are continuing an ongoing conversation. The previous messages in this conversation contain important context including:\n- Names, personal information, and preferences shared by the user\n- Projects, tasks, and topics discussed previously \n- Any decisions, agreements, or conclusions reached\n\nAlways reference and build upon this conversation history when relevant. If the user asks about information mentioned earlier in the conversation, refer to those previous messages to provide accurate, contextual responses.";
23
+ /**
24
+ * Get default configuration values for conversation memory
25
+ * Reads environment variables when called (not at module load time)
26
+ */
27
+ export declare function getConversationMemoryDefaults(): ConversationMemoryConfig;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Conversation Memory Configuration
3
+ * Provides default values for conversation memory feature with environment variable support
4
+ */
5
+ /**
6
+ * Default maximum number of turns per session
7
+ */
8
+ export const DEFAULT_MAX_TURNS_PER_SESSION = 50;
9
+ /**
10
+ * Default maximum number of sessions
11
+ */
12
+ export const DEFAULT_MAX_SESSIONS = 50;
13
+ /**
14
+ * Number of messages per conversation turn (user + assistant)
15
+ */
16
+ export const MESSAGES_PER_TURN = 2;
17
+ /**
18
+ * Conversation instructions for ongoing conversations
19
+ * Used to enhance system prompts when conversation history exists
20
+ */
21
+ export const CONVERSATION_INSTRUCTIONS = `
22
+
23
+ IMPORTANT: You are continuing an ongoing conversation. The previous messages in this conversation contain important context including:
24
+ - Names, personal information, and preferences shared by the user
25
+ - Projects, tasks, and topics discussed previously
26
+ - Any decisions, agreements, or conclusions reached
27
+
28
+ Always reference and build upon this conversation history when relevant. If the user asks about information mentioned earlier in the conversation, refer to those previous messages to provide accurate, contextual responses.`;
29
+ /**
30
+ * Get default configuration values for conversation memory
31
+ * Reads environment variables when called (not at module load time)
32
+ */
33
+ export function getConversationMemoryDefaults() {
34
+ return {
35
+ enabled: process.env.NEUROLINK_MEMORY_ENABLED === "true",
36
+ maxSessions: Number(process.env.NEUROLINK_MEMORY_MAX_SESSIONS) || DEFAULT_MAX_SESSIONS,
37
+ maxTurnsPerSession: Number(process.env.NEUROLINK_MEMORY_MAX_TURNS_PER_SESSION) || DEFAULT_MAX_TURNS_PER_SESSION,
38
+ };
39
+ }
@@ -0,0 +1,28 @@
1
+ import type { TextGenerationOptions, TextGenerationResult } from "../core/types.js";
2
+ import type { ContextManagerConfig } from "./types.js";
3
+ type InternalGenerator = (options: TextGenerationOptions) => Promise<TextGenerationResult>;
4
+ /**
5
+ * Manages conversation context, automatically summarizing it when it
6
+ * exceeds a specified word count limit.
7
+ */
8
+ export declare class ContextManager {
9
+ private static readonly SUMMARIZATION_FAILED_WARNING;
10
+ private static readonly SUMMARIZATION_EMPTY_WARNING;
11
+ private history;
12
+ private wordCount;
13
+ private readonly internalGenerator;
14
+ private readonly config;
15
+ constructor(generatorFunction: InternalGenerator, config: ContextManagerConfig, initialContext?: string);
16
+ addTurn(role: "user" | "assistant", message: string): Promise<void>;
17
+ /**
18
+ * Formats the history including the latest user turn for the prompt, without modifying the permanent history.
19
+ */
20
+ getContextForPrompt(role: "user", message: string): string;
21
+ getCurrentContext(): string;
22
+ private _summarize;
23
+ /**
24
+ * Truncates the history to a specific word count, preserving the most recent messages.
25
+ */
26
+ private _truncateHistory;
27
+ }
28
+ export {};