@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/dist/lib/neurolink.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { StreamOptions, StreamResult } from "./types/streamTypes.js";
|
|
|
11
11
|
import type { SimpleTool } from "./sdk/toolRegistration.js";
|
|
12
12
|
import type { InMemoryMCPServerConfig } from "./types/mcpTypes.js";
|
|
13
13
|
import { EventEmitter } from "events";
|
|
14
|
+
import type { ConversationMemoryConfig } from "./types/conversationTypes.js";
|
|
14
15
|
export interface ProviderStatus {
|
|
15
16
|
provider: string;
|
|
16
17
|
status: "working" | "failed" | "not-configured";
|
|
@@ -55,7 +56,10 @@ export declare class NeuroLink {
|
|
|
55
56
|
* @param success - Whether the tool execution was successful
|
|
56
57
|
*/
|
|
57
58
|
private emitToolEndEvent;
|
|
58
|
-
|
|
59
|
+
private conversationMemory?;
|
|
60
|
+
constructor(config?: {
|
|
61
|
+
conversationMemory?: Partial<ConversationMemoryConfig>;
|
|
62
|
+
});
|
|
59
63
|
/**
|
|
60
64
|
* Initialize MCP registry with enhanced error handling and resource cleanup
|
|
61
65
|
* Uses isolated async context to prevent hanging
|
|
@@ -75,9 +79,11 @@ export declare class NeuroLink {
|
|
|
75
79
|
* REDESIGNED INTERNAL GENERATION - NO CIRCULAR DEPENDENCIES
|
|
76
80
|
*
|
|
77
81
|
* This method implements a clean fallback chain:
|
|
78
|
-
* 1.
|
|
79
|
-
* 2.
|
|
80
|
-
* 3.
|
|
82
|
+
* 1. Initialize conversation memory if enabled
|
|
83
|
+
* 2. Inject conversation history into prompt
|
|
84
|
+
* 3. Try MCP-enhanced generation if available
|
|
85
|
+
* 4. Fall back to direct provider generation
|
|
86
|
+
* 5. Store conversation turn for future context
|
|
81
87
|
*/
|
|
82
88
|
private generateTextInternal;
|
|
83
89
|
/**
|
|
@@ -367,6 +373,18 @@ export declare class NeuroLink {
|
|
|
367
373
|
recommendations: string[];
|
|
368
374
|
}>;
|
|
369
375
|
};
|
|
376
|
+
/**
|
|
377
|
+
* Get conversation memory statistics (public API)
|
|
378
|
+
*/
|
|
379
|
+
getConversationStats(): Promise<import("./types/conversationTypes.js").ConversationMemoryStats>;
|
|
380
|
+
/**
|
|
381
|
+
* Clear conversation history for a specific session (public API)
|
|
382
|
+
*/
|
|
383
|
+
clearConversationSession(sessionId: string): Promise<boolean>;
|
|
384
|
+
/**
|
|
385
|
+
* Clear all conversation history (public API)
|
|
386
|
+
*/
|
|
387
|
+
clearAllConversations(): Promise<void>;
|
|
370
388
|
}
|
|
371
389
|
export declare const neurolink: NeuroLink;
|
|
372
390
|
export default neurolink;
|
package/dist/lib/neurolink.js
CHANGED
|
@@ -27,6 +27,8 @@ import { processFactoryOptions, enhanceTextGenerationOptions, validateFactoryCon
|
|
|
27
27
|
// Enhanced error handling imports
|
|
28
28
|
import { ErrorFactory, NeuroLinkError, withTimeout, withRetry, isRetriableError, logStructuredError, CircuitBreaker, } from "./utils/errorHandling.js";
|
|
29
29
|
import { EventEmitter } from "events";
|
|
30
|
+
import { ConversationMemoryManager } from "./core/conversationMemoryManager.js";
|
|
31
|
+
import { applyConversationMemoryDefaults, getConversationMessages, storeConversationTurn, } from "./utils/conversationMemoryUtils.js";
|
|
30
32
|
// Core types imported from core/types.js
|
|
31
33
|
export class NeuroLink {
|
|
32
34
|
mcpInitialized = false;
|
|
@@ -52,11 +54,22 @@ export class NeuroLink {
|
|
|
52
54
|
timestamp: Date.now(),
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
|
-
|
|
57
|
+
// Conversation memory support
|
|
58
|
+
conversationMemory;
|
|
59
|
+
constructor(config) {
|
|
56
60
|
// SDK always disables manual MCP config for security
|
|
57
61
|
ProviderRegistry.setOptions({
|
|
58
62
|
enableManualMCP: false,
|
|
59
63
|
});
|
|
64
|
+
// Initialize conversation memory if enabled
|
|
65
|
+
if (config?.conversationMemory?.enabled) {
|
|
66
|
+
const memoryConfig = applyConversationMemoryDefaults(config.conversationMemory);
|
|
67
|
+
this.conversationMemory = new ConversationMemoryManager(memoryConfig);
|
|
68
|
+
logger.info("NeuroLink initialized with conversation memory", {
|
|
69
|
+
maxSessions: memoryConfig.maxSessions,
|
|
70
|
+
maxTurnsPerSession: memoryConfig.maxTurnsPerSession,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
60
73
|
}
|
|
61
74
|
/**
|
|
62
75
|
* Initialize MCP registry with enhanced error handling and resource cleanup
|
|
@@ -247,9 +260,11 @@ export class NeuroLink {
|
|
|
247
260
|
* REDESIGNED INTERNAL GENERATION - NO CIRCULAR DEPENDENCIES
|
|
248
261
|
*
|
|
249
262
|
* This method implements a clean fallback chain:
|
|
250
|
-
* 1.
|
|
251
|
-
* 2.
|
|
252
|
-
* 3.
|
|
263
|
+
* 1. Initialize conversation memory if enabled
|
|
264
|
+
* 2. Inject conversation history into prompt
|
|
265
|
+
* 3. Try MCP-enhanced generation if available
|
|
266
|
+
* 4. Fall back to direct provider generation
|
|
267
|
+
* 5. Store conversation turn for future context
|
|
253
268
|
*/
|
|
254
269
|
async generateTextInternal(options) {
|
|
255
270
|
const startTime = Date.now();
|
|
@@ -257,14 +272,21 @@ export class NeuroLink {
|
|
|
257
272
|
logger.debug(`[${functionTag}] Starting generation`, {
|
|
258
273
|
provider: options.provider || "auto",
|
|
259
274
|
promptLength: options.prompt?.length || 0,
|
|
275
|
+
hasConversationMemory: !!this.conversationMemory,
|
|
260
276
|
});
|
|
261
277
|
try {
|
|
278
|
+
// Initialize conversation memory if enabled
|
|
279
|
+
if (this.conversationMemory) {
|
|
280
|
+
await this.conversationMemory.initialize();
|
|
281
|
+
}
|
|
262
282
|
// Try MCP-enhanced generation first (if not explicitly disabled)
|
|
263
283
|
if (!options.disableTools) {
|
|
264
284
|
try {
|
|
265
285
|
const mcpResult = await this.tryMCPGeneration(options);
|
|
266
286
|
if (mcpResult && mcpResult.content) {
|
|
267
287
|
logger.debug(`[${functionTag}] MCP generation successful`);
|
|
288
|
+
// Store conversation turn
|
|
289
|
+
await storeConversationTurn(this.conversationMemory, options, mcpResult);
|
|
268
290
|
return mcpResult;
|
|
269
291
|
}
|
|
270
292
|
}
|
|
@@ -277,6 +299,8 @@ export class NeuroLink {
|
|
|
277
299
|
// Fall back to direct provider generation
|
|
278
300
|
const directResult = await this.directProviderGeneration(options);
|
|
279
301
|
logger.debug(`[${functionTag}] Direct generation successful`);
|
|
302
|
+
// Store conversation turn
|
|
303
|
+
await storeConversationTurn(this.conversationMemory, options, directResult);
|
|
280
304
|
return directResult;
|
|
281
305
|
}
|
|
282
306
|
catch (error) {
|
|
@@ -334,6 +358,8 @@ export class NeuroLink {
|
|
|
334
358
|
}
|
|
335
359
|
// Create tool-aware system prompt
|
|
336
360
|
const enhancedSystemPrompt = this.createToolAwareSystemPrompt(options.systemPrompt, availableTools);
|
|
361
|
+
// Get conversation messages for context
|
|
362
|
+
const conversationMessages = await getConversationMessages(this.conversationMemory, options);
|
|
337
363
|
// Create provider and generate
|
|
338
364
|
const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
|
|
339
365
|
this);
|
|
@@ -345,6 +371,7 @@ export class NeuroLink {
|
|
|
345
371
|
const result = await provider.generate({
|
|
346
372
|
...options,
|
|
347
373
|
systemPrompt: enhancedSystemPrompt,
|
|
374
|
+
conversationMessages, // Inject conversation history
|
|
348
375
|
});
|
|
349
376
|
const responseTime = Date.now() - startTime;
|
|
350
377
|
// Check if result is meaningful
|
|
@@ -413,6 +440,8 @@ export class NeuroLink {
|
|
|
413
440
|
for (const providerName of tryProviders) {
|
|
414
441
|
try {
|
|
415
442
|
logger.debug(`[${functionTag}] Attempting provider: ${providerName}`);
|
|
443
|
+
// Get conversation messages for context
|
|
444
|
+
const conversationMessages = await getConversationMessages(this.conversationMemory, options);
|
|
416
445
|
const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
|
|
417
446
|
this);
|
|
418
447
|
// Enable tool execution for direct provider generation using BaseProvider method
|
|
@@ -420,7 +449,10 @@ export class NeuroLink {
|
|
|
420
449
|
customTools: this.customTools,
|
|
421
450
|
executeTool: this.executeTool.bind(this),
|
|
422
451
|
}, functionTag);
|
|
423
|
-
const result = await provider.generate(
|
|
452
|
+
const result = await provider.generate({
|
|
453
|
+
...options,
|
|
454
|
+
conversationMessages, // Inject conversation history
|
|
455
|
+
});
|
|
424
456
|
const responseTime = Date.now() - startTime;
|
|
425
457
|
if (!result) {
|
|
426
458
|
throw new Error(`Provider ${providerName} returned null result`);
|
|
@@ -1577,6 +1609,36 @@ export class NeuroLink {
|
|
|
1577
1609
|
tools,
|
|
1578
1610
|
};
|
|
1579
1611
|
}
|
|
1612
|
+
// ============================================================================
|
|
1613
|
+
// CONVERSATION MEMORY PUBLIC API
|
|
1614
|
+
// ============================================================================
|
|
1615
|
+
/**
|
|
1616
|
+
* Get conversation memory statistics (public API)
|
|
1617
|
+
*/
|
|
1618
|
+
async getConversationStats() {
|
|
1619
|
+
if (!this.conversationMemory) {
|
|
1620
|
+
throw new Error("Conversation memory is not enabled");
|
|
1621
|
+
}
|
|
1622
|
+
return await this.conversationMemory.getStats();
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* Clear conversation history for a specific session (public API)
|
|
1626
|
+
*/
|
|
1627
|
+
async clearConversationSession(sessionId) {
|
|
1628
|
+
if (!this.conversationMemory) {
|
|
1629
|
+
throw new Error("Conversation memory is not enabled");
|
|
1630
|
+
}
|
|
1631
|
+
return await this.conversationMemory.clearSession(sessionId);
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Clear all conversation history (public API)
|
|
1635
|
+
*/
|
|
1636
|
+
async clearAllConversations() {
|
|
1637
|
+
if (!this.conversationMemory) {
|
|
1638
|
+
throw new Error("Conversation memory is not enabled");
|
|
1639
|
+
}
|
|
1640
|
+
await this.conversationMemory.clearAllSessions();
|
|
1641
|
+
}
|
|
1580
1642
|
}
|
|
1581
1643
|
// Create default instance
|
|
1582
1644
|
export const neurolink = new NeuroLink();
|
|
@@ -5,6 +5,7 @@ import { logger } from "../utils/logger.js";
|
|
|
5
5
|
import { TimeoutError, } from "../utils/timeout.js";
|
|
6
6
|
import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
|
|
7
7
|
import { validateApiKey, createAWSAccessKeyConfig, createAWSSecretConfig, getAWSRegion, getAWSSessionToken, } from "../utils/providerConfig.js";
|
|
8
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
8
9
|
// Configuration helpers
|
|
9
10
|
const getBedrockModelId = () => {
|
|
10
11
|
return (process.env.BEDROCK_MODEL ||
|
|
@@ -79,10 +80,11 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
79
80
|
async executeStream(options, analysisSchema) {
|
|
80
81
|
try {
|
|
81
82
|
this.validateStreamOptions(options);
|
|
83
|
+
// Build message array from options
|
|
84
|
+
const messages = buildMessagesArray(options);
|
|
82
85
|
const result = await streamText({
|
|
83
86
|
model: this.model,
|
|
84
|
-
|
|
85
|
-
system: options.systemPrompt,
|
|
87
|
+
messages: messages,
|
|
86
88
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
87
89
|
temperature: options.temperature,
|
|
88
90
|
});
|
|
@@ -5,6 +5,7 @@ import { logger } from "../utils/logger.js";
|
|
|
5
5
|
import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
6
6
|
import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
7
7
|
import { validateApiKey, createAnthropicConfig, getProviderModel, } from "../utils/providerConfig.js";
|
|
8
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
8
9
|
// Configuration helpers - now using consolidated utility
|
|
9
10
|
const getAnthropicApiKey = () => {
|
|
10
11
|
return validateApiKey(createAnthropicConfig());
|
|
@@ -94,10 +95,11 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
94
95
|
// ✅ Get tools for streaming (same as generate method)
|
|
95
96
|
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
96
97
|
const tools = shouldUseTools ? await this.getAllTools() : {};
|
|
98
|
+
// Build message array from options
|
|
99
|
+
const messages = buildMessagesArray(options);
|
|
97
100
|
const result = await streamText({
|
|
98
101
|
model: this.model,
|
|
99
|
-
|
|
100
|
-
system: options.systemPrompt || undefined,
|
|
102
|
+
messages: messages,
|
|
101
103
|
temperature: options.temperature,
|
|
102
104
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
103
105
|
tools,
|
|
@@ -3,6 +3,7 @@ import { streamText } from "ai";
|
|
|
3
3
|
import { BaseProvider } from "../core/baseProvider.js";
|
|
4
4
|
import { validateApiKey, createAzureAPIKeyConfig, createAzureEndpointConfig, } from "../utils/providerConfig.js";
|
|
5
5
|
import { logger } from "../utils/logger.js";
|
|
6
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
6
7
|
export class AzureOpenAIProvider extends BaseProvider {
|
|
7
8
|
apiKey;
|
|
8
9
|
resourceName;
|
|
@@ -69,12 +70,13 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
69
70
|
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
70
71
|
async executeStream(options, analysisSchema) {
|
|
71
72
|
try {
|
|
73
|
+
// Build message array from options
|
|
74
|
+
const messages = buildMessagesArray(options);
|
|
72
75
|
const stream = await streamText({
|
|
73
76
|
model: this.azureProvider(this.deployment),
|
|
74
|
-
|
|
77
|
+
messages: messages,
|
|
75
78
|
maxTokens: options.maxTokens || 1000,
|
|
76
79
|
temperature: options.temperature || 0.7,
|
|
77
|
-
system: options.systemPrompt,
|
|
78
80
|
});
|
|
79
81
|
return {
|
|
80
82
|
stream: (async function* () {
|
|
@@ -6,6 +6,7 @@ import { logger } from "../utils/logger.js";
|
|
|
6
6
|
import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
7
7
|
import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
8
8
|
import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
|
|
9
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
9
10
|
// Environment variable setup
|
|
10
11
|
if (!process.env.GOOGLE_GENERATIVE_AI_API_KEY &&
|
|
11
12
|
process.env.GOOGLE_AI_API_KEY) {
|
|
@@ -76,10 +77,11 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
76
77
|
// Get tools consistently with generate method
|
|
77
78
|
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
78
79
|
const tools = shouldUseTools ? await this.getAllTools() : {};
|
|
80
|
+
// Build message array from options
|
|
81
|
+
const messages = buildMessagesArray(options);
|
|
79
82
|
const result = await streamText({
|
|
80
83
|
model,
|
|
81
|
-
|
|
82
|
-
system: options.systemPrompt,
|
|
84
|
+
messages: messages,
|
|
83
85
|
temperature: options.temperature,
|
|
84
86
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
85
87
|
tools,
|
|
@@ -6,6 +6,7 @@ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
|
6
6
|
import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
7
7
|
import { ModelConfigurationManager } from "../core/modelConfiguration.js";
|
|
8
8
|
import { validateApiKey, createVertexProjectConfig, createGoogleAuthConfig, } from "../utils/providerConfig.js";
|
|
9
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
9
10
|
// Cache for anthropic module to avoid repeated imports
|
|
10
11
|
let _createVertexAnthropic = null;
|
|
11
12
|
let _anthropicImportAttempted = false;
|
|
@@ -189,6 +190,8 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
189
190
|
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
|
|
190
191
|
try {
|
|
191
192
|
this.validateStreamOptions(options);
|
|
193
|
+
// Build message array from options
|
|
194
|
+
const messages = buildMessagesArray(options);
|
|
192
195
|
logger.debug(`${functionTag}: Starting stream request`, {
|
|
193
196
|
modelName: this.modelName,
|
|
194
197
|
promptLength: options.input.text.length,
|
|
@@ -209,8 +212,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
209
212
|
// Build complete stream options with proper typing
|
|
210
213
|
let streamOptions = {
|
|
211
214
|
model: model,
|
|
212
|
-
|
|
213
|
-
system: options.systemPrompt,
|
|
215
|
+
messages: messages,
|
|
214
216
|
temperature: options.temperature,
|
|
215
217
|
...(maxTokens && { maxTokens }),
|
|
216
218
|
tools,
|
|
@@ -5,6 +5,7 @@ import { logger } from "../utils/logger.js";
|
|
|
5
5
|
import { createTimeoutController, TimeoutError } from "../utils/timeout.js";
|
|
6
6
|
import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
|
|
7
7
|
import { validateApiKey, createHuggingFaceConfig, getProviderModel, } from "../utils/providerConfig.js";
|
|
8
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
8
9
|
// Configuration helpers - now using consolidated utility
|
|
9
10
|
const getHuggingFaceApiKey = () => {
|
|
10
11
|
return validateApiKey(createHuggingFaceConfig());
|
|
@@ -111,10 +112,11 @@ export class HuggingFaceProvider extends BaseProvider {
|
|
|
111
112
|
try {
|
|
112
113
|
// Enhanced tool handling for HuggingFace models
|
|
113
114
|
const streamOptions = this.prepareStreamOptions(options, analysisSchema);
|
|
115
|
+
// Build message array from options
|
|
116
|
+
const messages = buildMessagesArray(options);
|
|
114
117
|
const result = await streamText({
|
|
115
118
|
model: this.model,
|
|
116
|
-
|
|
117
|
-
system: streamOptions.system,
|
|
119
|
+
messages: messages,
|
|
118
120
|
temperature: options.temperature,
|
|
119
121
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
120
122
|
tools: streamOptions.tools, // Tools format conversion handled by prepareStreamOptions
|
|
@@ -6,6 +6,7 @@ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
|
6
6
|
import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
|
|
7
7
|
import { getProviderModel } from "../utils/providerConfig.js";
|
|
8
8
|
import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
|
|
9
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
9
10
|
// Configuration helpers
|
|
10
11
|
const getLiteLLMConfig = () => {
|
|
11
12
|
return {
|
|
@@ -118,10 +119,11 @@ export class LiteLLMProvider extends BaseProvider {
|
|
|
118
119
|
const timeout = this.getTimeout(options);
|
|
119
120
|
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
|
|
120
121
|
try {
|
|
122
|
+
// Build message array from options
|
|
123
|
+
const messages = buildMessagesArray(options);
|
|
121
124
|
const result = await streamText({
|
|
122
125
|
model: this.model,
|
|
123
|
-
|
|
124
|
-
system: options.systemPrompt,
|
|
126
|
+
messages: messages,
|
|
125
127
|
temperature: options.temperature,
|
|
126
128
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
127
129
|
tools: options.tools,
|
|
@@ -6,6 +6,7 @@ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
|
6
6
|
import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
7
7
|
import { validateApiKey, createMistralConfig, getProviderModel, } from "../utils/providerConfig.js";
|
|
8
8
|
import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
|
|
9
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
9
10
|
// Configuration helpers - now using consolidated utility
|
|
10
11
|
const getMistralApiKey = () => {
|
|
11
12
|
return validateApiKey(createMistralConfig());
|
|
@@ -46,10 +47,10 @@ export class MistralProvider extends BaseProvider {
|
|
|
46
47
|
// Get tools consistently with generate method
|
|
47
48
|
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
48
49
|
const tools = shouldUseTools ? await this.getAllTools() : {};
|
|
50
|
+
const messages = buildMessagesArray(options);
|
|
49
51
|
const result = await streamText({
|
|
50
52
|
model: this.model,
|
|
51
|
-
|
|
52
|
-
system: options.systemPrompt,
|
|
53
|
+
messages: messages,
|
|
53
54
|
temperature: options.temperature,
|
|
54
55
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
55
56
|
tools,
|
|
@@ -7,6 +7,7 @@ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
|
7
7
|
import { DEFAULT_MAX_TOKENS, DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
8
8
|
import { validateApiKey, createOpenAIConfig, getProviderModel, } from "../utils/providerConfig.js";
|
|
9
9
|
import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
|
|
10
|
+
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
10
11
|
// Configuration helpers - now using consolidated utility
|
|
11
12
|
const getOpenAIApiKey = () => {
|
|
12
13
|
return validateApiKey(createOpenAIConfig());
|
|
@@ -77,10 +78,11 @@ export class OpenAIProvider extends BaseProvider {
|
|
|
77
78
|
// Get tools consistently with generate method
|
|
78
79
|
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
79
80
|
const tools = shouldUseTools ? await this.getAllTools() : {};
|
|
81
|
+
// Build message array from options
|
|
82
|
+
const messages = buildMessagesArray(options);
|
|
80
83
|
const result = await streamText({
|
|
81
84
|
model: this.model,
|
|
82
|
-
|
|
83
|
-
system: options.systemPrompt,
|
|
85
|
+
messages: messages,
|
|
84
86
|
temperature: options.temperature,
|
|
85
87
|
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
86
88
|
tools,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation Memory Types for NeuroLink
|
|
3
|
+
* Provides type-safe conversation storage and context management
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for conversation memory feature
|
|
7
|
+
*/
|
|
8
|
+
export interface ConversationMemoryConfig {
|
|
9
|
+
/** Enable conversation memory feature */
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
/** Maximum number of sessions to keep in memory (default: 50) */
|
|
12
|
+
maxSessions?: number;
|
|
13
|
+
/** Maximum number of conversation turns to keep per session (default: 20) */
|
|
14
|
+
maxTurnsPerSession?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Complete memory for a conversation session
|
|
18
|
+
* ULTRA-OPTIMIZED: Direct ChatMessage[] storage - zero conversion overhead
|
|
19
|
+
*/
|
|
20
|
+
export interface SessionMemory {
|
|
21
|
+
/** Unique session identifier */
|
|
22
|
+
sessionId: string;
|
|
23
|
+
/** User identifier (optional) */
|
|
24
|
+
userId?: string;
|
|
25
|
+
/** Direct message storage - ready for immediate AI consumption */
|
|
26
|
+
messages: ChatMessage[];
|
|
27
|
+
/** When this session was created */
|
|
28
|
+
createdAt: number;
|
|
29
|
+
/** When this session was last active */
|
|
30
|
+
lastActivity: number;
|
|
31
|
+
/** Optional session metadata */
|
|
32
|
+
metadata?: {
|
|
33
|
+
/** User role or permissions */
|
|
34
|
+
userRole?: string;
|
|
35
|
+
/** Tags for categorizing this session */
|
|
36
|
+
tags?: string[];
|
|
37
|
+
/** Custom data specific to the organization */
|
|
38
|
+
customData?: Record<string, unknown>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Statistics about conversation memory usage (simplified for pure in-memory storage)
|
|
43
|
+
*/
|
|
44
|
+
export interface ConversationMemoryStats {
|
|
45
|
+
/** Total number of active sessions */
|
|
46
|
+
totalSessions: number;
|
|
47
|
+
/** Total number of conversation turns across all sessions */
|
|
48
|
+
totalTurns: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Chat message format for conversation history
|
|
52
|
+
*/
|
|
53
|
+
export interface ChatMessage {
|
|
54
|
+
/** Role of the message sender */
|
|
55
|
+
role: "user" | "assistant" | "system";
|
|
56
|
+
/** Content of the message */
|
|
57
|
+
content: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Events emitted by conversation memory system
|
|
61
|
+
*/
|
|
62
|
+
export interface ConversationMemoryEvents {
|
|
63
|
+
/** Emitted when a new session is created */
|
|
64
|
+
"session:created": {
|
|
65
|
+
sessionId: string;
|
|
66
|
+
userId?: string;
|
|
67
|
+
timestamp: number;
|
|
68
|
+
};
|
|
69
|
+
/** Emitted when a conversation turn is stored */
|
|
70
|
+
"turn:stored": {
|
|
71
|
+
sessionId: string;
|
|
72
|
+
turnIndex: number;
|
|
73
|
+
timestamp: number;
|
|
74
|
+
};
|
|
75
|
+
/** Emitted when a session is cleaned up */
|
|
76
|
+
"session:cleanup": {
|
|
77
|
+
sessionId: string;
|
|
78
|
+
reason: "expired" | "limit_exceeded";
|
|
79
|
+
timestamp: number;
|
|
80
|
+
};
|
|
81
|
+
/** Emitted when context is injected */
|
|
82
|
+
"context:injected": {
|
|
83
|
+
sessionId: string;
|
|
84
|
+
turnsIncluded: number;
|
|
85
|
+
timestamp: number;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Error types specific to conversation memory
|
|
90
|
+
*/
|
|
91
|
+
export declare class ConversationMemoryError extends Error {
|
|
92
|
+
code: "STORAGE_ERROR" | "CONFIG_ERROR" | "SESSION_NOT_FOUND" | "CLEANUP_ERROR";
|
|
93
|
+
details?: Record<string, unknown> | undefined;
|
|
94
|
+
constructor(message: string, code: "STORAGE_ERROR" | "CONFIG_ERROR" | "SESSION_NOT_FOUND" | "CLEANUP_ERROR", details?: Record<string, unknown> | undefined);
|
|
95
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation Memory Types for NeuroLink
|
|
3
|
+
* Provides type-safe conversation storage and context management
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Error types specific to conversation memory
|
|
7
|
+
*/
|
|
8
|
+
export class ConversationMemoryError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
details;
|
|
11
|
+
constructor(message, code, details) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.details = details;
|
|
15
|
+
this.name = "ConversationMemoryError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { ZodType, ZodTypeDef } from "zod";
|
|
|
2
2
|
import type { Tool, Schema } from "ai";
|
|
3
3
|
import type { AIProviderName, AnalyticsData, EvaluationData } from "../core/types.js";
|
|
4
4
|
import type { UnknownRecord, JsonValue } from "./common.js";
|
|
5
|
+
import type { ChatMessage } from "./conversationTypes.js";
|
|
5
6
|
/**
|
|
6
7
|
* Interface for tool execution calls (AI SDK compatible)
|
|
7
8
|
*/
|
|
@@ -107,6 +108,7 @@ export interface StreamOptions {
|
|
|
107
108
|
enableProgress?: boolean;
|
|
108
109
|
fallbackToGenerate?: boolean;
|
|
109
110
|
};
|
|
111
|
+
conversationMessages?: ChatMessage[];
|
|
110
112
|
}
|
|
111
113
|
/**
|
|
112
114
|
* Stream function result interface - Primary output format for streaming
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation Memory Utilities
|
|
3
|
+
* Handles configuration merging and conversation memory operations
|
|
4
|
+
*/
|
|
5
|
+
import type { ConversationMemoryConfig, ChatMessage } from "../types/conversationTypes.js";
|
|
6
|
+
import type { ConversationMemoryManager } from "../core/conversationMemoryManager.js";
|
|
7
|
+
import type { TextGenerationOptions, TextGenerationResult } from "../core/types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Apply conversation memory defaults to user configuration
|
|
10
|
+
* Merges user config with environment variables and default values
|
|
11
|
+
*/
|
|
12
|
+
export declare function applyConversationMemoryDefaults(userConfig?: Partial<ConversationMemoryConfig>): ConversationMemoryConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Get conversation history as message array (PREFERRED METHOD)
|
|
15
|
+
* Returns proper message array format for AI providers
|
|
16
|
+
*/
|
|
17
|
+
export declare function getConversationMessages(conversationMemory: ConversationMemoryManager | undefined, options: TextGenerationOptions): Promise<ChatMessage[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Store conversation turn for future context
|
|
20
|
+
* Saves user messages and AI responses for conversation memory
|
|
21
|
+
*/
|
|
22
|
+
export declare function storeConversationTurn(conversationMemory: ConversationMemoryManager | undefined, originalOptions: TextGenerationOptions, result: TextGenerationResult): Promise<void>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation Memory Utilities
|
|
3
|
+
* Handles configuration merging and conversation memory operations
|
|
4
|
+
*/
|
|
5
|
+
import { getConversationMemoryDefaults } from "../config/conversationMemoryConfig.js";
|
|
6
|
+
import { logger } from "./logger.js";
|
|
7
|
+
/**
|
|
8
|
+
* Apply conversation memory defaults to user configuration
|
|
9
|
+
* Merges user config with environment variables and default values
|
|
10
|
+
*/
|
|
11
|
+
export function applyConversationMemoryDefaults(userConfig) {
|
|
12
|
+
const defaults = getConversationMemoryDefaults();
|
|
13
|
+
return {
|
|
14
|
+
enabled: userConfig?.enabled ?? defaults.enabled,
|
|
15
|
+
maxSessions: userConfig?.maxSessions ?? defaults.maxSessions,
|
|
16
|
+
maxTurnsPerSession: userConfig?.maxTurnsPerSession ?? defaults.maxTurnsPerSession,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get conversation history as message array (PREFERRED METHOD)
|
|
21
|
+
* Returns proper message array format for AI providers
|
|
22
|
+
*/
|
|
23
|
+
export async function getConversationMessages(conversationMemory, options) {
|
|
24
|
+
if (!conversationMemory || !options.context) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const sessionId = options.context?.sessionId;
|
|
28
|
+
if (typeof sessionId !== "string" || !sessionId) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const messages = conversationMemory.buildContextMessages(sessionId);
|
|
33
|
+
logger.debug("Conversation messages retrieved", {
|
|
34
|
+
sessionId,
|
|
35
|
+
messageCount: messages.length,
|
|
36
|
+
});
|
|
37
|
+
return messages;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
logger.warn("Failed to get conversation messages", {
|
|
41
|
+
sessionId,
|
|
42
|
+
error: error instanceof Error ? error.message : String(error),
|
|
43
|
+
});
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Store conversation turn for future context
|
|
49
|
+
* Saves user messages and AI responses for conversation memory
|
|
50
|
+
*/
|
|
51
|
+
export async function storeConversationTurn(conversationMemory, originalOptions, result) {
|
|
52
|
+
if (!conversationMemory || !originalOptions.context) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const context = originalOptions.context;
|
|
56
|
+
const sessionId = context.sessionId;
|
|
57
|
+
const userId = typeof context.userId === "string" ? context.userId : undefined;
|
|
58
|
+
if (typeof sessionId !== "string" || !sessionId) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
await conversationMemory.storeConversationTurn(sessionId, userId, originalOptions.prompt || "", result.content);
|
|
63
|
+
logger.debug("Conversation turn stored", {
|
|
64
|
+
sessionId,
|
|
65
|
+
userId,
|
|
66
|
+
promptLength: originalOptions.prompt?.length || 0,
|
|
67
|
+
responseLength: result.content.length,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
logger.warn("Failed to store conversation turn", {
|
|
72
|
+
sessionId,
|
|
73
|
+
userId,
|
|
74
|
+
error: error instanceof Error ? error.message : String(error),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Builder Utility
|
|
3
|
+
* Centralized logic for building message arrays from TextGenerationOptions
|
|
4
|
+
*/
|
|
5
|
+
import type { ChatMessage } from "../types/conversationTypes.js";
|
|
6
|
+
import type { TextGenerationOptions } from "../core/types.js";
|
|
7
|
+
import type { StreamOptions } from "../types/streamTypes.js";
|
|
8
|
+
/**
|
|
9
|
+
* Build a properly formatted message array for AI providers
|
|
10
|
+
* Combines system prompt, conversation history, and current user prompt
|
|
11
|
+
* Supports both TextGenerationOptions and StreamOptions
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildMessagesArray(options: TextGenerationOptions | StreamOptions): ChatMessage[];
|