@juspay/neurolink 7.29.3 → 7.30.1

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 (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/config/conversationMemoryConfig.js +5 -0
  3. package/dist/core/conversationMemoryManager.d.ts +9 -15
  4. package/dist/core/conversationMemoryManager.js +103 -56
  5. package/dist/core/types.d.ts +3 -1
  6. package/dist/factories/providerRegistry.js +1 -1
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +2 -0
  9. package/dist/lib/config/conversationMemoryConfig.js +5 -0
  10. package/dist/lib/core/conversationMemoryManager.d.ts +9 -15
  11. package/dist/lib/core/conversationMemoryManager.js +103 -56
  12. package/dist/lib/core/types.d.ts +3 -1
  13. package/dist/lib/factories/providerRegistry.js +1 -1
  14. package/dist/lib/index.d.ts +2 -0
  15. package/dist/lib/index.js +2 -0
  16. package/dist/lib/neurolink.d.ts +0 -9
  17. package/dist/lib/neurolink.js +7 -39
  18. package/dist/lib/providers/amazonBedrock.d.ts +28 -59
  19. package/dist/lib/providers/amazonBedrock.js +913 -330
  20. package/dist/lib/types/conversationTypes.d.ts +10 -0
  21. package/dist/lib/types/generateTypes.d.ts +1 -2
  22. package/dist/lib/utils/conversationMemoryUtils.d.ts +1 -2
  23. package/dist/lib/utils/conversationMemoryUtils.js +5 -6
  24. package/dist/lib/utils/logger.d.ts +164 -4
  25. package/dist/lib/utils/logger.js +163 -10
  26. package/dist/lib/utils/providerUtils.js +9 -6
  27. package/dist/neurolink.d.ts +0 -9
  28. package/dist/neurolink.js +7 -39
  29. package/dist/providers/amazonBedrock.d.ts +28 -59
  30. package/dist/providers/amazonBedrock.js +913 -330
  31. package/dist/types/conversationTypes.d.ts +10 -0
  32. package/dist/types/generateTypes.d.ts +1 -2
  33. package/dist/utils/conversationMemoryUtils.d.ts +1 -2
  34. package/dist/utils/conversationMemoryUtils.js +5 -6
  35. package/dist/utils/logger.d.ts +164 -4
  36. package/dist/utils/logger.js +163 -10
  37. package/dist/utils/providerUtils.js +9 -6
  38. package/package.json +2 -3
  39. package/dist/context/ContextManager.d.ts +0 -28
  40. package/dist/context/ContextManager.js +0 -113
  41. package/dist/context/config.d.ts +0 -5
  42. package/dist/context/config.js +0 -42
  43. package/dist/context/types.d.ts +0 -20
  44. package/dist/context/types.js +0 -1
  45. package/dist/context/utils.d.ts +0 -7
  46. package/dist/context/utils.js +0 -8
  47. package/dist/lib/context/ContextManager.d.ts +0 -28
  48. package/dist/lib/context/ContextManager.js +0 -113
  49. package/dist/lib/context/config.d.ts +0 -5
  50. package/dist/lib/context/config.js +0 -42
  51. package/dist/lib/context/types.d.ts +0 -20
  52. package/dist/lib/context/types.js +0 -1
  53. package/dist/lib/context/utils.d.ts +0 -7
  54. package/dist/lib/context/utils.js +0 -8
  55. package/dist/lib/providers/aws/credentialProvider.d.ts +0 -58
  56. package/dist/lib/providers/aws/credentialProvider.js +0 -267
  57. package/dist/lib/providers/aws/credentialTester.d.ts +0 -49
  58. package/dist/lib/providers/aws/credentialTester.js +0 -394
  59. package/dist/providers/aws/credentialProvider.d.ts +0 -58
  60. package/dist/providers/aws/credentialProvider.js +0 -267
  61. package/dist/providers/aws/credentialTester.d.ts +0 -49
  62. package/dist/providers/aws/credentialTester.js +0 -394
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [7.30.1](https://github.com/juspay/neurolink/compare/v7.30.0...v7.30.1) (2025-08-31)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **(bedrock):** migrate from ai-sdk to native AWS SDK implementation ([e5d8a4c](https://github.com/juspay/neurolink/commit/e5d8a4c85144ed558167f5083abd89d125576ab0))
6
+
7
+ ## [7.30.0](https://github.com/juspay/neurolink/compare/v7.29.3...v7.30.0) (2025-08-29)
8
+
9
+ ### Features
10
+
11
+ - **(SDK):** Integrate context summarization with conversation memory BZ-43344 ([a2316ff](https://github.com/juspay/neurolink/commit/a2316ff6df55107316892d33365455e6ebdcbbd9))
12
+
1
13
  ## [7.29.3](https://github.com/juspay/neurolink/compare/v7.29.2...v7.29.3) (2025-08-29)
2
14
 
3
15
  ### Bug Fixes
@@ -36,5 +36,10 @@ export function getConversationMemoryDefaults() {
36
36
  maxSessions: Number(process.env.NEUROLINK_MEMORY_MAX_SESSIONS) || DEFAULT_MAX_SESSIONS,
37
37
  maxTurnsPerSession: Number(process.env.NEUROLINK_MEMORY_MAX_TURNS_PER_SESSION) ||
38
38
  DEFAULT_MAX_TURNS_PER_SESSION,
39
+ enableSummarization: process.env.NEUROLINK_SUMMARIZATION_ENABLED === "true",
40
+ summarizationThresholdTurns: Number(process.env.NEUROLINK_SUMMARIZATION_THRESHOLD_TURNS) || 20,
41
+ summarizationTargetTurns: Number(process.env.NEUROLINK_SUMMARIZATION_TARGET_TURNS) || 10,
42
+ summarizationProvider: process.env.NEUROLINK_SUMMARIZATION_PROVIDER || "vertex",
43
+ summarizationModel: process.env.NEUROLINK_SUMMARIZATION_MODEL || "gemini-2.5-flash",
39
44
  };
40
45
  }
@@ -2,10 +2,10 @@
2
2
  * Conversation Memory Manager for NeuroLink
3
3
  * Handles in-memory conversation storage, session management, and context injection
4
4
  */
5
- import type { ConversationMemoryConfig, ConversationMemoryStats, ChatMessage } from "../types/conversationTypes.js";
5
+ import type { ConversationMemoryConfig, SessionMemory, ConversationMemoryStats, ChatMessage } from "../types/conversationTypes.js";
6
6
  export declare class ConversationMemoryManager {
7
7
  private sessions;
8
- private config;
8
+ config: ConversationMemoryConfig;
9
9
  private isInitialized;
10
10
  constructor(config: ConversationMemoryConfig);
11
11
  /**
@@ -22,20 +22,14 @@ export declare class ConversationMemoryManager {
22
22
  * Returns pre-stored message array with zero conversion overhead
23
23
  */
24
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>;
25
+ getSession(sessionId: string): SessionMemory | undefined;
26
+ createSummarySystemMessage(content: string): ChatMessage;
27
+ private _summarizeSession;
28
+ private _createSummarizationPrompt;
38
29
  private ensureInitialized;
39
30
  private createNewSession;
40
31
  private enforceSessionLimit;
32
+ getStats(): Promise<ConversationMemoryStats>;
33
+ clearSession(sessionId: string): Promise<boolean>;
34
+ clearAllSessions(): Promise<void>;
41
35
  }
@@ -5,12 +5,12 @@
5
5
  import { ConversationMemoryError } from "../types/conversationTypes.js";
6
6
  import { DEFAULT_MAX_TURNS_PER_SESSION, DEFAULT_MAX_SESSIONS, MESSAGES_PER_TURN, } from "../config/conversationMemoryConfig.js";
7
7
  import { logger } from "../utils/logger.js";
8
+ import { NeuroLink } from "../neurolink.js";
8
9
  export class ConversationMemoryManager {
9
10
  sessions = new Map();
10
11
  config;
11
12
  isInitialized = false;
12
13
  constructor(config) {
13
- // Trust that config is already complete from applyConversationMemoryDefaults()
14
14
  this.config = config;
15
15
  }
16
16
  /**
@@ -48,21 +48,21 @@ export class ConversationMemoryManager {
48
48
  // ULTRA-OPTIMIZED: Direct message storage - no intermediate objects
49
49
  session.messages.push({ role: "user", content: userMessage }, { role: "assistant", content: aiResponse });
50
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) *
53
- MESSAGES_PER_TURN;
54
- if (session.messages.length > maxMessages) {
55
- session.messages = session.messages.slice(-maxMessages);
51
+ if (this.config.enableSummarization) {
52
+ const userAssistantCount = session.messages.filter((msg) => msg.role === "user" || msg.role === "assistant").length;
53
+ const currentTurnCount = Math.floor(userAssistantCount / MESSAGES_PER_TURN);
54
+ if (currentTurnCount >= (this.config.summarizationThresholdTurns || 20)) {
55
+ await this._summarizeSession(session);
56
+ }
57
+ }
58
+ else {
59
+ const maxMessages = (this.config.maxTurnsPerSession || DEFAULT_MAX_TURNS_PER_SESSION) *
60
+ MESSAGES_PER_TURN;
61
+ if (session.messages.length > maxMessages) {
62
+ session.messages = session.messages.slice(-maxMessages);
63
+ }
56
64
  }
57
- // Enforce global session limit
58
65
  this.enforceSessionLimit();
59
- logger.debug("Conversation turn stored", {
60
- sessionId,
61
- messageCount: session.messages.length,
62
- turnCount: session.messages.length / MESSAGES_PER_TURN, // Each turn = MESSAGES_PER_TURN messages
63
- userMessageLength: userMessage.length,
64
- aiResponseLength: aiResponse.length,
65
- });
66
66
  }
67
67
  catch (error) {
68
68
  throw new ConversationMemoryError(`Failed to store conversation turn for session ${sessionId}`, "STORAGE_ERROR", {
@@ -77,48 +77,78 @@ export class ConversationMemoryManager {
77
77
  */
78
78
  buildContextMessages(sessionId) {
79
79
  const session = this.sessions.get(sessionId);
80
- if (!session || session.messages.length === 0) {
81
- return [];
82
- }
83
- // ULTRA-OPTIMIZED: Direct return - no processing needed!
84
- return session.messages;
80
+ return session ? session.messages : [];
85
81
  }
86
- /**
87
- * Get memory statistics (simplified for pure in-memory storage)
88
- * ULTRA-OPTIMIZED: Calculate turns from message count (each turn = MESSAGES_PER_TURN messages)
89
- */
90
- async getStats() {
91
- await this.ensureInitialized();
92
- const sessions = Array.from(this.sessions.values());
93
- const totalTurns = sessions.reduce((sum, session) => sum + session.messages.length / MESSAGES_PER_TURN, 0);
82
+ getSession(sessionId) {
83
+ return this.sessions.get(sessionId);
84
+ }
85
+ createSummarySystemMessage(content) {
94
86
  return {
95
- totalSessions: sessions.length,
96
- totalTurns,
87
+ role: "system",
88
+ content: `Summary of previous conversation turns:\n\n${content}`,
97
89
  };
98
90
  }
99
- /**
100
- * Clear all conversations for a specific session
101
- */
102
- async clearSession(sessionId) {
103
- const session = this.sessions.get(sessionId);
104
- if (!session) {
105
- return false;
91
+ async _summarizeSession(session) {
92
+ logger.info(`[ConversationMemory] Summarizing session ${session.sessionId}...`);
93
+ const targetTurns = this.config.summarizationTargetTurns || 10;
94
+ const splitIndex = Math.max(0, session.messages.length - targetTurns * MESSAGES_PER_TURN);
95
+ const messagesToSummarize = session.messages.slice(0, splitIndex);
96
+ const recentMessages = session.messages.slice(splitIndex);
97
+ if (messagesToSummarize.length === 0) {
98
+ return;
99
+ }
100
+ const summarizationPrompt = this._createSummarizationPrompt(messagesToSummarize);
101
+ const summarizer = new NeuroLink({
102
+ conversationMemory: { enabled: false },
103
+ });
104
+ try {
105
+ const providerName = this.config.summarizationProvider;
106
+ // Map provider names to correct format
107
+ let mappedProvider = providerName;
108
+ if (providerName === "vertex") {
109
+ mappedProvider = "googlevertex";
110
+ }
111
+ if (!mappedProvider) {
112
+ logger.error(`[ConversationMemory] Missing summarization provider`);
113
+ return;
114
+ }
115
+ logger.debug(`[ConversationMemory] Using provider: ${mappedProvider} for summarization`);
116
+ const summaryResult = await summarizer.generate({
117
+ input: { text: summarizationPrompt },
118
+ provider: mappedProvider,
119
+ model: this.config.summarizationModel,
120
+ disableTools: true,
121
+ });
122
+ if (summaryResult.content) {
123
+ session.messages = [
124
+ this.createSummarySystemMessage(summaryResult.content),
125
+ ...recentMessages,
126
+ ];
127
+ logger.info(`[ConversationMemory] Summarization complete for session ${session.sessionId}.`);
128
+ }
129
+ else {
130
+ logger.warn(`[ConversationMemory] Summarization failed for session ${session.sessionId}. History not modified.`);
131
+ }
132
+ }
133
+ catch (error) {
134
+ logger.error(`[ConversationMemory] Error during summarization for session ${session.sessionId}`, { error });
106
135
  }
107
- // Remove from memory
108
- this.sessions.delete(sessionId);
109
- logger.info("Session cleared", { sessionId });
110
- return true;
111
136
  }
112
- /**
113
- * Clear all conversations (reset memory)
114
- */
115
- async clearAllSessions() {
116
- const sessionIds = Array.from(this.sessions.keys());
117
- // Clear memory
118
- this.sessions.clear();
119
- logger.info("All sessions cleared", { clearedCount: sessionIds.length });
137
+ _createSummarizationPrompt(history) {
138
+ const formattedHistory = history
139
+ .map((msg) => `${msg.role}: ${msg.content}`)
140
+ .join("\n\n");
141
+ return `
142
+ You are a context summarization AI. Your task is to condense the following conversation history for another AI assistant.
143
+ The summary must be a concise, third-person narrative that retains all critical information, including key entities, technical details, decisions made, and any specific dates or times mentioned.
144
+ Ensure the summary flows logically and is ready to be used as context for the next turn in the conversation.
145
+
146
+ Conversation History to Summarize:
147
+ ---
148
+ ${formattedHistory}
149
+ ---
150
+ `.trim();
120
151
  }
121
- // Private methods
122
152
  async ensureInitialized() {
123
153
  if (!this.isInitialized) {
124
154
  await this.initialize();
@@ -138,16 +168,33 @@ export class ConversationMemoryManager {
138
168
  if (this.sessions.size <= maxSessions) {
139
169
  return;
140
170
  }
141
- // Sort sessions by last activity (oldest first)
142
171
  const sessions = Array.from(this.sessions.entries()).sort(([, a], [, b]) => a.lastActivity - b.lastActivity);
143
- // Remove oldest sessions
144
- const sessionsToRemove = sessions.slice(0, sessions.length - maxSessions);
172
+ const sessionsToRemove = sessions.slice(0, this.sessions.size - maxSessions);
145
173
  for (const [sessionId] of sessionsToRemove) {
146
174
  this.sessions.delete(sessionId);
147
175
  }
148
- logger.debug("Session limit enforced", {
149
- removedSessions: sessionsToRemove.length,
150
- remainingSessions: this.sessions.size,
151
- });
176
+ }
177
+ async getStats() {
178
+ await this.ensureInitialized();
179
+ const sessions = Array.from(this.sessions.values());
180
+ const totalTurns = sessions.reduce((sum, session) => sum + session.messages.length / MESSAGES_PER_TURN, 0);
181
+ return {
182
+ totalSessions: sessions.length,
183
+ totalTurns,
184
+ };
185
+ }
186
+ async clearSession(sessionId) {
187
+ const session = this.sessions.get(sessionId);
188
+ if (!session) {
189
+ return false;
190
+ }
191
+ this.sessions.delete(sessionId);
192
+ logger.info("Session cleared", { sessionId });
193
+ return true;
194
+ }
195
+ async clearAllSessions() {
196
+ const sessionIds = Array.from(this.sessions.keys());
197
+ this.sessions.clear();
198
+ logger.info("All sessions cleared", { clearedCount: sessionIds.length });
152
199
  }
153
200
  }
@@ -3,7 +3,7 @@ import type { ZodUnknownSchema, ValidationSchema } from "../types/typeAliases.js
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
+ import type { ChatMessage, ConversationMemoryConfig } from "../types/conversationTypes.js";
7
7
  import type { TokenUsage, AnalyticsData } from "../types/providers.js";
8
8
  import type { EvaluationData } from "../index.js";
9
9
  export type { EvaluationData };
@@ -155,6 +155,8 @@ export interface TextGenerationOptions {
155
155
  content: string;
156
156
  }>;
157
157
  conversationMessages?: ChatMessage[];
158
+ conversationMemoryConfig?: Partial<ConversationMemoryConfig>;
159
+ originalPrompt?: string;
158
160
  expectedOutcome?: string;
159
161
  evaluationCriteria?: string[];
160
162
  }
@@ -41,7 +41,7 @@ export class ProviderRegistry {
41
41
  // Register Amazon Bedrock provider
42
42
  ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName, _providerName, sdk) => {
43
43
  const { AmazonBedrockProvider } = await import("../providers/amazonBedrock.js");
44
- return new AmazonBedrockProvider(modelName, undefined, sdk);
44
+ return new AmazonBedrockProvider(modelName, sdk);
45
45
  }, undefined, // Let provider read BEDROCK_MODEL from .env
46
46
  ["bedrock", "aws"]);
47
47
  // Register Azure OpenAI provider
package/dist/index.d.ts CHANGED
@@ -15,6 +15,8 @@ export { validateTool } from "./sdk/toolRegistration.js";
15
15
  export type { ToolResult, ToolDefinition } from "./types/tools.js";
16
16
  export { BedrockModels, OpenAIModels, VertexModels, DEFAULT_PROVIDER_CONFIGS, } from "./core/types.js";
17
17
  export { getBestProvider, getAvailableProviders, isValidProvider, } from "./utils/providerUtils.js";
18
+ export { dynamicModelProvider } from "./core/dynamicModels.js";
19
+ export type { ModelConfig, ModelRegistry } from "./core/dynamicModels.js";
18
20
  export { NeuroLink } from "./neurolink.js";
19
21
  export type { ProviderStatus, MCPStatus } from "./neurolink.js";
20
22
  export type { MCPServerInfo } from "./types/mcpTypes.js";
package/dist/index.js CHANGED
@@ -14,6 +14,8 @@ export { validateTool } from "./sdk/toolRegistration.js";
14
14
  export { BedrockModels, OpenAIModels, VertexModels, DEFAULT_PROVIDER_CONFIGS, } from "./core/types.js";
15
15
  // Utility exports
16
16
  export { getBestProvider, getAvailableProviders, isValidProvider, } from "./utils/providerUtils.js";
17
+ // Dynamic Models exports
18
+ export { dynamicModelProvider } from "./core/dynamicModels.js";
17
19
  // Main NeuroLink wrapper class and diagnostic types
18
20
  export { NeuroLink } from "./neurolink.js";
19
21
  export { MiddlewareFactory } from "./middleware/factory.js";
@@ -36,5 +36,10 @@ export function getConversationMemoryDefaults() {
36
36
  maxSessions: Number(process.env.NEUROLINK_MEMORY_MAX_SESSIONS) || DEFAULT_MAX_SESSIONS,
37
37
  maxTurnsPerSession: Number(process.env.NEUROLINK_MEMORY_MAX_TURNS_PER_SESSION) ||
38
38
  DEFAULT_MAX_TURNS_PER_SESSION,
39
+ enableSummarization: process.env.NEUROLINK_SUMMARIZATION_ENABLED === "true",
40
+ summarizationThresholdTurns: Number(process.env.NEUROLINK_SUMMARIZATION_THRESHOLD_TURNS) || 20,
41
+ summarizationTargetTurns: Number(process.env.NEUROLINK_SUMMARIZATION_TARGET_TURNS) || 10,
42
+ summarizationProvider: process.env.NEUROLINK_SUMMARIZATION_PROVIDER || "vertex",
43
+ summarizationModel: process.env.NEUROLINK_SUMMARIZATION_MODEL || "gemini-2.5-flash",
39
44
  };
40
45
  }
@@ -2,10 +2,10 @@
2
2
  * Conversation Memory Manager for NeuroLink
3
3
  * Handles in-memory conversation storage, session management, and context injection
4
4
  */
5
- import type { ConversationMemoryConfig, ConversationMemoryStats, ChatMessage } from "../types/conversationTypes.js";
5
+ import type { ConversationMemoryConfig, SessionMemory, ConversationMemoryStats, ChatMessage } from "../types/conversationTypes.js";
6
6
  export declare class ConversationMemoryManager {
7
7
  private sessions;
8
- private config;
8
+ config: ConversationMemoryConfig;
9
9
  private isInitialized;
10
10
  constructor(config: ConversationMemoryConfig);
11
11
  /**
@@ -22,20 +22,14 @@ export declare class ConversationMemoryManager {
22
22
  * Returns pre-stored message array with zero conversion overhead
23
23
  */
24
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>;
25
+ getSession(sessionId: string): SessionMemory | undefined;
26
+ createSummarySystemMessage(content: string): ChatMessage;
27
+ private _summarizeSession;
28
+ private _createSummarizationPrompt;
38
29
  private ensureInitialized;
39
30
  private createNewSession;
40
31
  private enforceSessionLimit;
32
+ getStats(): Promise<ConversationMemoryStats>;
33
+ clearSession(sessionId: string): Promise<boolean>;
34
+ clearAllSessions(): Promise<void>;
41
35
  }
@@ -5,12 +5,12 @@
5
5
  import { ConversationMemoryError } from "../types/conversationTypes.js";
6
6
  import { DEFAULT_MAX_TURNS_PER_SESSION, DEFAULT_MAX_SESSIONS, MESSAGES_PER_TURN, } from "../config/conversationMemoryConfig.js";
7
7
  import { logger } from "../utils/logger.js";
8
+ import { NeuroLink } from "../neurolink.js";
8
9
  export class ConversationMemoryManager {
9
10
  sessions = new Map();
10
11
  config;
11
12
  isInitialized = false;
12
13
  constructor(config) {
13
- // Trust that config is already complete from applyConversationMemoryDefaults()
14
14
  this.config = config;
15
15
  }
16
16
  /**
@@ -48,21 +48,21 @@ export class ConversationMemoryManager {
48
48
  // ULTRA-OPTIMIZED: Direct message storage - no intermediate objects
49
49
  session.messages.push({ role: "user", content: userMessage }, { role: "assistant", content: aiResponse });
50
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) *
53
- MESSAGES_PER_TURN;
54
- if (session.messages.length > maxMessages) {
55
- session.messages = session.messages.slice(-maxMessages);
51
+ if (this.config.enableSummarization) {
52
+ const userAssistantCount = session.messages.filter((msg) => msg.role === "user" || msg.role === "assistant").length;
53
+ const currentTurnCount = Math.floor(userAssistantCount / MESSAGES_PER_TURN);
54
+ if (currentTurnCount >= (this.config.summarizationThresholdTurns || 20)) {
55
+ await this._summarizeSession(session);
56
+ }
57
+ }
58
+ else {
59
+ const maxMessages = (this.config.maxTurnsPerSession || DEFAULT_MAX_TURNS_PER_SESSION) *
60
+ MESSAGES_PER_TURN;
61
+ if (session.messages.length > maxMessages) {
62
+ session.messages = session.messages.slice(-maxMessages);
63
+ }
56
64
  }
57
- // Enforce global session limit
58
65
  this.enforceSessionLimit();
59
- logger.debug("Conversation turn stored", {
60
- sessionId,
61
- messageCount: session.messages.length,
62
- turnCount: session.messages.length / MESSAGES_PER_TURN, // Each turn = MESSAGES_PER_TURN messages
63
- userMessageLength: userMessage.length,
64
- aiResponseLength: aiResponse.length,
65
- });
66
66
  }
67
67
  catch (error) {
68
68
  throw new ConversationMemoryError(`Failed to store conversation turn for session ${sessionId}`, "STORAGE_ERROR", {
@@ -77,48 +77,78 @@ export class ConversationMemoryManager {
77
77
  */
78
78
  buildContextMessages(sessionId) {
79
79
  const session = this.sessions.get(sessionId);
80
- if (!session || session.messages.length === 0) {
81
- return [];
82
- }
83
- // ULTRA-OPTIMIZED: Direct return - no processing needed!
84
- return session.messages;
80
+ return session ? session.messages : [];
85
81
  }
86
- /**
87
- * Get memory statistics (simplified for pure in-memory storage)
88
- * ULTRA-OPTIMIZED: Calculate turns from message count (each turn = MESSAGES_PER_TURN messages)
89
- */
90
- async getStats() {
91
- await this.ensureInitialized();
92
- const sessions = Array.from(this.sessions.values());
93
- const totalTurns = sessions.reduce((sum, session) => sum + session.messages.length / MESSAGES_PER_TURN, 0);
82
+ getSession(sessionId) {
83
+ return this.sessions.get(sessionId);
84
+ }
85
+ createSummarySystemMessage(content) {
94
86
  return {
95
- totalSessions: sessions.length,
96
- totalTurns,
87
+ role: "system",
88
+ content: `Summary of previous conversation turns:\n\n${content}`,
97
89
  };
98
90
  }
99
- /**
100
- * Clear all conversations for a specific session
101
- */
102
- async clearSession(sessionId) {
103
- const session = this.sessions.get(sessionId);
104
- if (!session) {
105
- return false;
91
+ async _summarizeSession(session) {
92
+ logger.info(`[ConversationMemory] Summarizing session ${session.sessionId}...`);
93
+ const targetTurns = this.config.summarizationTargetTurns || 10;
94
+ const splitIndex = Math.max(0, session.messages.length - targetTurns * MESSAGES_PER_TURN);
95
+ const messagesToSummarize = session.messages.slice(0, splitIndex);
96
+ const recentMessages = session.messages.slice(splitIndex);
97
+ if (messagesToSummarize.length === 0) {
98
+ return;
99
+ }
100
+ const summarizationPrompt = this._createSummarizationPrompt(messagesToSummarize);
101
+ const summarizer = new NeuroLink({
102
+ conversationMemory: { enabled: false },
103
+ });
104
+ try {
105
+ const providerName = this.config.summarizationProvider;
106
+ // Map provider names to correct format
107
+ let mappedProvider = providerName;
108
+ if (providerName === "vertex") {
109
+ mappedProvider = "googlevertex";
110
+ }
111
+ if (!mappedProvider) {
112
+ logger.error(`[ConversationMemory] Missing summarization provider`);
113
+ return;
114
+ }
115
+ logger.debug(`[ConversationMemory] Using provider: ${mappedProvider} for summarization`);
116
+ const summaryResult = await summarizer.generate({
117
+ input: { text: summarizationPrompt },
118
+ provider: mappedProvider,
119
+ model: this.config.summarizationModel,
120
+ disableTools: true,
121
+ });
122
+ if (summaryResult.content) {
123
+ session.messages = [
124
+ this.createSummarySystemMessage(summaryResult.content),
125
+ ...recentMessages,
126
+ ];
127
+ logger.info(`[ConversationMemory] Summarization complete for session ${session.sessionId}.`);
128
+ }
129
+ else {
130
+ logger.warn(`[ConversationMemory] Summarization failed for session ${session.sessionId}. History not modified.`);
131
+ }
132
+ }
133
+ catch (error) {
134
+ logger.error(`[ConversationMemory] Error during summarization for session ${session.sessionId}`, { error });
106
135
  }
107
- // Remove from memory
108
- this.sessions.delete(sessionId);
109
- logger.info("Session cleared", { sessionId });
110
- return true;
111
136
  }
112
- /**
113
- * Clear all conversations (reset memory)
114
- */
115
- async clearAllSessions() {
116
- const sessionIds = Array.from(this.sessions.keys());
117
- // Clear memory
118
- this.sessions.clear();
119
- logger.info("All sessions cleared", { clearedCount: sessionIds.length });
137
+ _createSummarizationPrompt(history) {
138
+ const formattedHistory = history
139
+ .map((msg) => `${msg.role}: ${msg.content}`)
140
+ .join("\n\n");
141
+ return `
142
+ You are a context summarization AI. Your task is to condense the following conversation history for another AI assistant.
143
+ The summary must be a concise, third-person narrative that retains all critical information, including key entities, technical details, decisions made, and any specific dates or times mentioned.
144
+ Ensure the summary flows logically and is ready to be used as context for the next turn in the conversation.
145
+
146
+ Conversation History to Summarize:
147
+ ---
148
+ ${formattedHistory}
149
+ ---
150
+ `.trim();
120
151
  }
121
- // Private methods
122
152
  async ensureInitialized() {
123
153
  if (!this.isInitialized) {
124
154
  await this.initialize();
@@ -138,16 +168,33 @@ export class ConversationMemoryManager {
138
168
  if (this.sessions.size <= maxSessions) {
139
169
  return;
140
170
  }
141
- // Sort sessions by last activity (oldest first)
142
171
  const sessions = Array.from(this.sessions.entries()).sort(([, a], [, b]) => a.lastActivity - b.lastActivity);
143
- // Remove oldest sessions
144
- const sessionsToRemove = sessions.slice(0, sessions.length - maxSessions);
172
+ const sessionsToRemove = sessions.slice(0, this.sessions.size - maxSessions);
145
173
  for (const [sessionId] of sessionsToRemove) {
146
174
  this.sessions.delete(sessionId);
147
175
  }
148
- logger.debug("Session limit enforced", {
149
- removedSessions: sessionsToRemove.length,
150
- remainingSessions: this.sessions.size,
151
- });
176
+ }
177
+ async getStats() {
178
+ await this.ensureInitialized();
179
+ const sessions = Array.from(this.sessions.values());
180
+ const totalTurns = sessions.reduce((sum, session) => sum + session.messages.length / MESSAGES_PER_TURN, 0);
181
+ return {
182
+ totalSessions: sessions.length,
183
+ totalTurns,
184
+ };
185
+ }
186
+ async clearSession(sessionId) {
187
+ const session = this.sessions.get(sessionId);
188
+ if (!session) {
189
+ return false;
190
+ }
191
+ this.sessions.delete(sessionId);
192
+ logger.info("Session cleared", { sessionId });
193
+ return true;
194
+ }
195
+ async clearAllSessions() {
196
+ const sessionIds = Array.from(this.sessions.keys());
197
+ this.sessions.clear();
198
+ logger.info("All sessions cleared", { clearedCount: sessionIds.length });
152
199
  }
153
200
  }
@@ -3,7 +3,7 @@ import type { ZodUnknownSchema, ValidationSchema } from "../types/typeAliases.js
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
+ import type { ChatMessage, ConversationMemoryConfig } from "../types/conversationTypes.js";
7
7
  import type { TokenUsage, AnalyticsData } from "../types/providers.js";
8
8
  import type { EvaluationData } from "../index.js";
9
9
  export type { EvaluationData };
@@ -155,6 +155,8 @@ export interface TextGenerationOptions {
155
155
  content: string;
156
156
  }>;
157
157
  conversationMessages?: ChatMessage[];
158
+ conversationMemoryConfig?: Partial<ConversationMemoryConfig>;
159
+ originalPrompt?: string;
158
160
  expectedOutcome?: string;
159
161
  evaluationCriteria?: string[];
160
162
  }
@@ -41,7 +41,7 @@ export class ProviderRegistry {
41
41
  // Register Amazon Bedrock provider
42
42
  ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName, _providerName, sdk) => {
43
43
  const { AmazonBedrockProvider } = await import("../providers/amazonBedrock.js");
44
- return new AmazonBedrockProvider(modelName, undefined, sdk);
44
+ return new AmazonBedrockProvider(modelName, sdk);
45
45
  }, undefined, // Let provider read BEDROCK_MODEL from .env
46
46
  ["bedrock", "aws"]);
47
47
  // Register Azure OpenAI provider
@@ -15,6 +15,8 @@ export { validateTool } from "./sdk/toolRegistration.js";
15
15
  export type { ToolResult, ToolDefinition } from "./types/tools.js";
16
16
  export { BedrockModels, OpenAIModels, VertexModels, DEFAULT_PROVIDER_CONFIGS, } from "./core/types.js";
17
17
  export { getBestProvider, getAvailableProviders, isValidProvider, } from "./utils/providerUtils.js";
18
+ export { dynamicModelProvider } from "./core/dynamicModels.js";
19
+ export type { ModelConfig, ModelRegistry } from "./core/dynamicModels.js";
18
20
  export { NeuroLink } from "./neurolink.js";
19
21
  export type { ProviderStatus, MCPStatus } from "./neurolink.js";
20
22
  export type { MCPServerInfo } from "./types/mcpTypes.js";
package/dist/lib/index.js CHANGED
@@ -14,6 +14,8 @@ export { validateTool } from "./sdk/toolRegistration.js";
14
14
  export { BedrockModels, OpenAIModels, VertexModels, DEFAULT_PROVIDER_CONFIGS, } from "./core/types.js";
15
15
  // Utility exports
16
16
  export { getBestProvider, getAvailableProviders, isValidProvider, } from "./utils/providerUtils.js";
17
+ // Dynamic Models exports
18
+ export { dynamicModelProvider } from "./core/dynamicModels.js";
17
19
  // Main NeuroLink wrapper class and diagnostic types
18
20
  export { NeuroLink } from "./neurolink.js";
19
21
  export { MiddlewareFactory } from "./middleware/factory.js";