@juspay/neurolink 7.11.0 → 7.12.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.
- package/CHANGELOG.md +12 -0
- package/README.md +15 -0
- package/dist/config/conversationMemoryConfig.d.ts +27 -0
- package/dist/config/conversationMemoryConfig.js +39 -0
- package/dist/core/baseProvider.js +4 -2
- package/dist/core/conversationMemoryManager.d.ts +41 -0
- package/dist/core/conversationMemoryManager.js +152 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/lib/config/conversationMemoryConfig.d.ts +27 -0
- package/dist/lib/config/conversationMemoryConfig.js +39 -0
- package/dist/lib/core/baseProvider.js +4 -2
- package/dist/lib/core/conversationMemoryManager.d.ts +41 -0
- package/dist/lib/core/conversationMemoryManager.js +152 -0
- package/dist/lib/core/types.d.ts +2 -0
- package/dist/lib/neurolink.d.ts +22 -4
- package/dist/lib/neurolink.js +67 -5
- package/dist/lib/providers/amazonBedrock.js +4 -2
- package/dist/lib/providers/anthropic.js +4 -2
- package/dist/lib/providers/azureOpenai.js +4 -2
- package/dist/lib/providers/googleAiStudio.js +4 -2
- package/dist/lib/providers/googleVertex.js +4 -2
- package/dist/lib/providers/huggingFace.js +4 -2
- package/dist/lib/providers/litellm.js +4 -2
- package/dist/lib/providers/mistral.js +3 -2
- package/dist/lib/providers/openAI.js +4 -2
- package/dist/lib/types/conversationTypes.d.ts +95 -0
- package/dist/lib/types/conversationTypes.js +17 -0
- package/dist/lib/types/streamTypes.d.ts +2 -0
- package/dist/lib/utils/conversationMemoryUtils.d.ts +22 -0
- package/dist/lib/utils/conversationMemoryUtils.js +77 -0
- package/dist/lib/utils/messageBuilder.d.ts +13 -0
- package/dist/lib/utils/messageBuilder.js +48 -0
- package/dist/neurolink.d.ts +22 -4
- package/dist/neurolink.js +67 -5
- package/dist/providers/amazonBedrock.js +4 -2
- package/dist/providers/anthropic.js +4 -2
- package/dist/providers/azureOpenai.js +4 -2
- package/dist/providers/googleAiStudio.js +4 -2
- package/dist/providers/googleVertex.js +4 -2
- package/dist/providers/huggingFace.js +4 -2
- package/dist/providers/litellm.js +4 -2
- package/dist/providers/mistral.js +3 -2
- package/dist/providers/openAI.js +4 -2
- package/dist/types/conversationTypes.d.ts +95 -0
- package/dist/types/conversationTypes.js +17 -0
- package/dist/types/streamTypes.d.ts +2 -0
- package/dist/utils/conversationMemoryUtils.d.ts +22 -0
- package/dist/utils/conversationMemoryUtils.js +77 -0
- package/dist/utils/messageBuilder.d.ts +13 -0
- package/dist/utils/messageBuilder.js +48 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [7.12.0](https://github.com/juspay/neurolink/compare/v7.11.1...v7.12.0) (2025-08-14)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **(memory):** Added support for Conversation History ([5cf3650](https://github.com/juspay/neurolink/commit/5cf36507ec12fca525df652c1c15acc8c1c71297))
|
|
6
|
+
|
|
7
|
+
## [7.11.1](https://github.com/juspay/neurolink/compare/v7.11.0...v7.11.1) (2025-08-14)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **(ci):** add external contributor detection to GitHub Copilot PR Review workflow ([c7d9f2c](https://github.com/juspay/neurolink/commit/c7d9f2cf8d1d0079b34e443a935a84d4a53adf9a))
|
|
12
|
+
|
|
1
13
|
## [7.11.0](https://github.com/juspay/neurolink/compare/v7.10.3...v7.11.0) (2025-08-14)
|
|
2
14
|
|
|
3
15
|
### Features
|
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:
|
|
@@ -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
|
+
}
|
|
@@ -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
|
-
|
|
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
|
+
}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -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
|
+
}
|
|
@@ -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
|
-
|
|
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
|
+
}
|
package/dist/lib/core/types.d.ts
CHANGED
|
@@ -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
|