@juspay/neurolink 13.8.15 โ 13.8.16
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 +2 -2
- package/dist/browser/neurolink.min.js +3 -3
- package/dist/core/conversationMemoryFactory.d.ts +2 -2
- package/dist/core/conversationMemoryFactory.js +2 -2
- package/dist/core/conversationMemoryInitializer.d.ts +2 -2
- package/dist/core/conversationMemoryInitializer.js +2 -2
- package/dist/core/redisConversationMemoryManager.d.ts +13 -2
- package/dist/core/redisConversationMemoryManager.js +31 -1
- package/dist/neurolink.js +1 -1
- package/dist/types/common.d.ts +2 -1
- package/dist/types/conversation.d.ts +12 -0
- package/docs-site/static/search-index.json +4 -2
- package/package.json +1 -1
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Conversation Memory Factory for NeuroLink
|
|
3
3
|
* Creates appropriate conversation memory manager based on configuration
|
|
4
4
|
*/
|
|
5
|
-
import type { StorageType, ConversationMemoryConfig, RedisStorageConfig } from "../types/index.js";
|
|
5
|
+
import type { StorageType, ConversationMemoryConfig, NeuroLinkEvents, RedisStorageConfig, TypedEventEmitter } from "../types/index.js";
|
|
6
6
|
import { ConversationMemoryManager } from "./conversationMemoryManager.js";
|
|
7
7
|
import { RedisConversationMemoryManager } from "./redisConversationMemoryManager.js";
|
|
8
8
|
/**
|
|
9
9
|
* Creates a conversation memory manager based on configuration
|
|
10
10
|
*/
|
|
11
|
-
export declare function createConversationMemoryManager(config: ConversationMemoryConfig, storageType?: StorageType, redisConfig?: RedisStorageConfig): ConversationMemoryManager | RedisConversationMemoryManager;
|
|
11
|
+
export declare function createConversationMemoryManager(config: ConversationMemoryConfig, storageType?: StorageType, redisConfig?: RedisStorageConfig, eventEmitter?: TypedEventEmitter<NeuroLinkEvents>): ConversationMemoryManager | RedisConversationMemoryManager;
|
|
12
12
|
/**
|
|
13
13
|
* Get storage type from environment variable or configuration
|
|
14
14
|
*/
|
|
@@ -8,7 +8,7 @@ import { RedisConversationMemoryManager } from "./redisConversationMemoryManager
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates a conversation memory manager based on configuration
|
|
10
10
|
*/
|
|
11
|
-
export function createConversationMemoryManager(config, storageType = "memory", redisConfig) {
|
|
11
|
+
export function createConversationMemoryManager(config, storageType = "memory", redisConfig, eventEmitter) {
|
|
12
12
|
logger.debug("[conversationMemoryFactory] Creating conversation memory manager", {
|
|
13
13
|
storageType,
|
|
14
14
|
config: {
|
|
@@ -38,7 +38,7 @@ export function createConversationMemoryManager(config, storageType = "memory",
|
|
|
38
38
|
ttl: redisConfig?.ttl || 86400,
|
|
39
39
|
hasConnectionOptions: !!redisConfig?.connectionOptions,
|
|
40
40
|
});
|
|
41
|
-
const redisManager = new RedisConversationMemoryManager(config, redisConfig);
|
|
41
|
+
const redisManager = new RedisConversationMemoryManager(config, redisConfig, eventEmitter);
|
|
42
42
|
logger.debug("[conversationMemoryFactory] Redis conversation manager created successfully", {
|
|
43
43
|
managerType: redisManager.constructor.name,
|
|
44
44
|
config: {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Conversation Memory Initializer
|
|
3
3
|
* Provides integration with Redis storage for conversation memory
|
|
4
4
|
*/
|
|
5
|
-
import type { ConversationMemoryConfig } from "../types/index.js";
|
|
5
|
+
import type { ConversationMemoryConfig, NeuroLinkEvents, TypedEventEmitter } from "../types/index.js";
|
|
6
6
|
import type { ConversationMemoryManager } from "./conversationMemoryManager.js";
|
|
7
7
|
import type { RedisConversationMemoryManager } from "./redisConversationMemoryManager.js";
|
|
8
8
|
/**
|
|
@@ -11,4 +11,4 @@ import type { RedisConversationMemoryManager } from "./redisConversationMemoryMa
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function initializeConversationMemory(config?: {
|
|
13
13
|
conversationMemory?: Partial<ConversationMemoryConfig>;
|
|
14
|
-
}): Promise<ConversationMemoryManager | RedisConversationMemoryManager | null>;
|
|
14
|
+
}, eventEmitter?: TypedEventEmitter<NeuroLinkEvents>): Promise<ConversationMemoryManager | RedisConversationMemoryManager | null>;
|
|
@@ -9,7 +9,7 @@ import { createConversationMemoryManager, getRedisConfigFromEnv, getStorageType,
|
|
|
9
9
|
* Initialize conversation memory for NeuroLink
|
|
10
10
|
* This function decides whether to use in-memory or Redis storage
|
|
11
11
|
*/
|
|
12
|
-
export async function initializeConversationMemory(config) {
|
|
12
|
+
export async function initializeConversationMemory(config, eventEmitter) {
|
|
13
13
|
logger.debug("[conversationMemoryInitializer] Initialize conversation memory called", {
|
|
14
14
|
hasConfig: !!config,
|
|
15
15
|
hasMemoryConfig: !!config?.conversationMemory,
|
|
@@ -58,7 +58,7 @@ export async function initializeConversationMemory(config) {
|
|
|
58
58
|
});
|
|
59
59
|
// Create Redis-based conversation memory manager
|
|
60
60
|
logger.debug("[conversationMemoryInitializer] Creating Redis conversation memory manager");
|
|
61
|
-
const redisMemoryManager = createConversationMemoryManager(memoryConfig, "redis", redisConfig);
|
|
61
|
+
const redisMemoryManager = createConversationMemoryManager(memoryConfig, "redis", redisConfig, eventEmitter);
|
|
62
62
|
logger.debug("[conversationMemoryInitializer] Checking Redis manager creation result", {
|
|
63
63
|
managerType: redisMemoryManager?.constructor?.name || "unknown",
|
|
64
64
|
isRedisType: redisMemoryManager?.constructor?.name ===
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Redis Conversation Memory Manager for NeuroLink
|
|
3
3
|
* Redis-based implementation of conversation storage with same interface as ConversationMemoryManager
|
|
4
4
|
*/
|
|
5
|
-
import type { ChatMessage, ConversationMemoryConfig, ConversationMemoryStats, RedisConversationObject, RedisStorageConfig, SessionListItem, SessionMemory, SessionMetadata, StoreConversationTurnOptions, AgenticLoopReportMetadata, IConversationMemoryManager } from "../types/index.js";
|
|
5
|
+
import type { ChatMessage, ConversationMemoryConfig, ConversationMemoryStats, RedisConversationObject, RedisStorageConfig, SessionListItem, SessionMemory, SessionMetadata, StoreConversationTurnOptions, AgenticLoopReportMetadata, IConversationMemoryManager, NeuroLinkEvents, TypedEventEmitter } from "../types/index.js";
|
|
6
6
|
/**
|
|
7
7
|
* Redis-based implementation of the ConversationMemoryManager
|
|
8
8
|
* Uses the same interface but stores data in Redis
|
|
@@ -13,6 +13,11 @@ export declare class RedisConversationMemoryManager implements IConversationMemo
|
|
|
13
13
|
private summarizationEngine;
|
|
14
14
|
private redisConfig;
|
|
15
15
|
private redisClient;
|
|
16
|
+
/**
|
|
17
|
+
* Receives `conversation:titleGenerated` once a new conversation's title is
|
|
18
|
+
* stored. Optional because the manager can be constructed standalone.
|
|
19
|
+
*/
|
|
20
|
+
private readonly eventEmitter?;
|
|
16
21
|
/**
|
|
17
22
|
* Temporary storage for tool execution data to prevent race conditions
|
|
18
23
|
* Key format: "${sessionId}:${userId}"
|
|
@@ -28,7 +33,7 @@ export declare class RedisConversationMemoryManager implements IConversationMemo
|
|
|
28
33
|
* Key format: "${sessionId}:${userId}"
|
|
29
34
|
*/
|
|
30
35
|
private summarizationInProgress;
|
|
31
|
-
constructor(config: ConversationMemoryConfig, redisConfig?: RedisStorageConfig);
|
|
36
|
+
constructor(config: ConversationMemoryConfig, redisConfig?: RedisStorageConfig, eventEmitter?: TypedEventEmitter<NeuroLinkEvents>);
|
|
32
37
|
/**
|
|
33
38
|
* Initialize the memory manager with Redis connection
|
|
34
39
|
*/
|
|
@@ -155,6 +160,12 @@ export declare class RedisConversationMemoryManager implements IConversationMemo
|
|
|
155
160
|
* @returns Complete conversation object with all data, or null if session doesn't exist
|
|
156
161
|
*/
|
|
157
162
|
getUserSessionObject(userId: string, sessionId: string): Promise<RedisConversationObject | null>;
|
|
163
|
+
/**
|
|
164
|
+
* Announce a stored title. A throwing listener is logged rather than
|
|
165
|
+
* propagated: the title is already persisted, and the caller's catch block
|
|
166
|
+
* reports title-generation failures.
|
|
167
|
+
*/
|
|
168
|
+
private emitTitleGenerated;
|
|
158
169
|
/**
|
|
159
170
|
* Generate a conversation title from the first user message
|
|
160
171
|
* Uses AI to create a concise, descriptive title (5-8 words)
|
|
@@ -29,6 +29,11 @@ export class RedisConversationMemoryManager {
|
|
|
29
29
|
summarizationEngine = new SummarizationEngine();
|
|
30
30
|
redisConfig;
|
|
31
31
|
redisClient = null;
|
|
32
|
+
/**
|
|
33
|
+
* Receives `conversation:titleGenerated` once a new conversation's title is
|
|
34
|
+
* stored. Optional because the manager can be constructed standalone.
|
|
35
|
+
*/
|
|
36
|
+
eventEmitter;
|
|
32
37
|
/**
|
|
33
38
|
* Temporary storage for tool execution data to prevent race conditions
|
|
34
39
|
* Key format: "${sessionId}:${userId}"
|
|
@@ -44,9 +49,10 @@ export class RedisConversationMemoryManager {
|
|
|
44
49
|
* Key format: "${sessionId}:${userId}"
|
|
45
50
|
*/
|
|
46
51
|
summarizationInProgress = new Set();
|
|
47
|
-
constructor(config, redisConfig = {}) {
|
|
52
|
+
constructor(config, redisConfig = {}, eventEmitter) {
|
|
48
53
|
this.config = config;
|
|
49
54
|
this.redisConfig = getNormalizedConfig(redisConfig);
|
|
55
|
+
this.eventEmitter = eventEmitter;
|
|
50
56
|
}
|
|
51
57
|
/**
|
|
52
58
|
* Initialize the memory manager with Redis connection
|
|
@@ -419,6 +425,12 @@ export class RedisConversationMemoryManager {
|
|
|
419
425
|
const serializedData = serializeConversation(updatedConversation);
|
|
420
426
|
if (this.redisClient) {
|
|
421
427
|
await setWithTtl(this.redisClient, updatedRedisKey, serializedData, this.redisConfig.ttl);
|
|
428
|
+
this.emitTitleGenerated({
|
|
429
|
+
sessionId: options.sessionId,
|
|
430
|
+
userId: normalizedUserId,
|
|
431
|
+
title,
|
|
432
|
+
timestamp: Date.now(),
|
|
433
|
+
});
|
|
422
434
|
}
|
|
423
435
|
}
|
|
424
436
|
}
|
|
@@ -1023,6 +1035,24 @@ export class RedisConversationMemoryManager {
|
|
|
1023
1035
|
return null;
|
|
1024
1036
|
}
|
|
1025
1037
|
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Announce a stored title. A throwing listener is logged rather than
|
|
1040
|
+
* propagated: the title is already persisted, and the caller's catch block
|
|
1041
|
+
* reports title-generation failures.
|
|
1042
|
+
*/
|
|
1043
|
+
emitTitleGenerated(event) {
|
|
1044
|
+
try {
|
|
1045
|
+
this.eventEmitter?.emit("conversation:titleGenerated", event);
|
|
1046
|
+
}
|
|
1047
|
+
catch (listenerError) {
|
|
1048
|
+
logger.warn("[RedisConversationMemoryManager] conversation:titleGenerated listener threw", {
|
|
1049
|
+
sessionId: event.sessionId,
|
|
1050
|
+
error: listenerError instanceof Error
|
|
1051
|
+
? listenerError.message
|
|
1052
|
+
: String(listenerError),
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1026
1056
|
/**
|
|
1027
1057
|
* Generate a conversation title from the first user message
|
|
1028
1058
|
* Uses AI to create a concise, descriptive title (5-8 words)
|
package/dist/neurolink.js
CHANGED
|
@@ -13851,7 +13851,7 @@ Current user's request: ${currentInput}`;
|
|
|
13851
13851
|
// Import the integration module
|
|
13852
13852
|
const { initializeConversationMemory } = await import("./core/conversationMemoryInitializer.js");
|
|
13853
13853
|
// Use the integration module to create the appropriate memory manager
|
|
13854
|
-
const memoryManager = await initializeConversationMemory(this.conversationMemoryConfig);
|
|
13854
|
+
const memoryManager = await initializeConversationMemory(this.conversationMemoryConfig, this.emitter);
|
|
13855
13855
|
// Assign to conversationMemory with proper type to handle both memory manager types
|
|
13856
13856
|
this.conversationMemory = memoryManager;
|
|
13857
13857
|
// Reset the lazy init flag since we've now initialized
|
package/dist/types/common.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Common utility types for NeuroLink
|
|
3
3
|
*/
|
|
4
4
|
import type { NeuroLink } from "../neurolink.js";
|
|
5
|
-
import type { ConversationMemoryConfig } from "./conversation.js";
|
|
5
|
+
import type { ConversationMemoryConfig, ConversationTitleGeneratedEvent } from "./conversation.js";
|
|
6
6
|
import type { AutoresearchErrorEvent, AutoresearchExperimentCompletedEvent, AutoresearchExperimentStartedEvent, AutoresearchInitializedEvent, AutoresearchMetricImprovedEvent, AutoresearchPhaseChangedEvent, AutoresearchResumedEvent, AutoresearchRevertEvent, AutoresearchRevertFailedEvent, AutoresearchStateUpdatedEvent } from "./autoresearch.js";
|
|
7
7
|
/**
|
|
8
8
|
* Type-safe unknown value - use when type is truly unknown
|
|
@@ -120,6 +120,7 @@ export type NeuroLinkEvents = {
|
|
|
120
120
|
"externalMCP:serverRemoved": unknown;
|
|
121
121
|
"tools-register:start": unknown;
|
|
122
122
|
"tools-register:end": unknown;
|
|
123
|
+
"conversation:titleGenerated": ConversationTitleGeneratedEvent;
|
|
123
124
|
connected: unknown;
|
|
124
125
|
message: unknown;
|
|
125
126
|
error: unknown;
|
|
@@ -752,6 +752,18 @@ export type RedisConversationObject = ConversationBase & {
|
|
|
752
752
|
/** Array of conversation messages */
|
|
753
753
|
messages: ChatMessage[];
|
|
754
754
|
};
|
|
755
|
+
/**
|
|
756
|
+
* Payload of the `conversation:titleGenerated` event, emitted once the title
|
|
757
|
+
* of a new Redis-backed conversation has been stored.
|
|
758
|
+
*/
|
|
759
|
+
export type ConversationTitleGeneratedEvent = {
|
|
760
|
+
sessionId: string;
|
|
761
|
+
userId: string;
|
|
762
|
+
/** The title that was stored, which is what `listSessions()` reports. */
|
|
763
|
+
title: string;
|
|
764
|
+
/** Unix epoch milliseconds when the title was stored. */
|
|
765
|
+
timestamp: number;
|
|
766
|
+
};
|
|
755
767
|
/**
|
|
756
768
|
* Full conversation data for session restoration and manipulation
|
|
757
769
|
* Extends Redis storage object with additional loop mode metadata
|
|
@@ -8466,15 +8466,16 @@
|
|
|
8466
8466
|
{"objectID":"156003cd4819e4dbb7f346be7120ea605e8ad136ca867e2f736327744c48c281","title":"2. Best Practices","url":"/docs/mcp/testing#2-best-practices","content":"Use TypeScript for full type safety\nValidate inputs with Zod schemas\nHandle errors gracefully in tools\nLog execution for debugging\nTest thoroughly before deployment","hierarchy":{"lvl0":"Mcp","lvl1":"๐งช MCP Foundation Testing Guide","lvl2":"2. Best Practices","lvl3":""}},
|
|
8467
8467
|
{"objectID":"e772b5dca6bea98f96f9043b173ee610272e201d08879869318c2d8070425ffc","title":"3. Performance Monitoring","url":"/docs/mcp/testing#3-performance-monitoring","content":"3. Performance Monitoring","hierarchy":{"lvl0":"Mcp","lvl1":"๐งช MCP Foundation Testing Guide","lvl2":"3. Performance Monitoring","lvl3":""}},
|
|
8468
8468
|
{"objectID":"82c7cc03c75290cac4197443132e907f9796ad297a7a81df29ac6e5ae9c42734","title":"๐ Next Steps","url":"/docs/mcp/testing#-next-steps","content":"โ
Test Current Implementation - Use programmatic testing examples\n๐ง Add CLI Integration - Implement MCP CLI commands\n๐๏ธ Create Custom Servers - Build domain-specific tool servers\n๐ Monitor Performance - Track tool execution and usage\n๐ Iterate and Improve - Enhance based on real usage\n\nMCP Foundation is production-ready and waiting for your custom tools! ๐","hierarchy":{"lvl0":"Mcp","lvl1":"๐งช MCP Foundation Testing Guide","lvl2":"๐ Next Steps","lvl3":""}},
|
|
8469
|
-
{"objectID":"d287e2ebab877225d0b71aafb45118dd2b1d04914f8cf4cd8b2c82b12aba80b8","title":"Conversation Memory","url":"/docs/memory/conversation","content":"Conversation Memory\n\nNeuroLink's Conversation Memory feature enables AI models to maintain context across multiple turns within a session, creating more natural and coherent conversations.\n\n๐ง Overview\n\nThe conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses\n\nโ๏ธ Configuration\n\nEnvironment Variables\n\nProgrammatic Configuration\n\n๐ Usage Examples\n\nBasic Usage with Session ID\n\nStreaming Support\n\nThe conversation memory system now fully supports streaming responses with the same memory persistence:\n\nMixed Generate/Stream Conversations\n\nYou can seamlessly mix generate() and stream() calls within the same conversation:\n\nSession Isolation Example\n\n๐ Memory Management\n\nTurn Limits\n\nWhen the number of conversation turns exceeds maxTurnsPerSession, older messages are automatically removed:\n\nSession Limits\n\nWhen the number of active sessions exceeds maxSessions, the least recently used sessions are removed:\n\n๐ API Reference\n\nMemory Statistics\n\nSession Management\n\n๐งช Test Results\n\nThe conversation memory system has been thoroughly tested and validated:\n\nโ
Test Suite Results\n\n| Test Case | Status | Description |\n| --------------------- | ------- | ----------------------------------------------- |\n| Basic Memory | โ
PASS | AI correctly remembers information across turns |\n| Session Isolation | โ
PASS | Sessions remain completely separate |\n| Turn Limits | โ
PASS | Automatic cleanup when limits exceeded |\n| Session Limits | โ
PASS | LRU eviction of old sessions |\n| API Functions | โ
PASS | Clear operations work correctly |\n\nExample Test Output\n\n๐ก Best Practices\nSession ID Strategy\nMemory Limits\nError Handling\n\n๐ง Technical Implementation\n\nArchitecture\n\nMessage Format\n\n๐ Troubleshooting\n\nCommon Issues\n\nMemory not persisting between calls\nEnsure sessionId is consistent across calls\nVerify conversationMemory.enabled is true\nCheck that sessionId is a valid string\n\nPerformance issues with large conversations\nReduce maxTurnsPerSession limit\nImplement session cleanup strategies\nMonitor memory usage statistics\n\nSession isolation not working\nVerify different sessionId values are being used\nCheck for session ID conflicts or duplicates\n\nDebug Logging\n\n๐ Related Documentation\nRedis Conversation Export - Export session history as JSON for analytics\nAPI Reference - Complete SDK documentation\nConfiguration - Environment setup guide\nExamples - More usage examples\nTesting Guide - How to test conversation memory\n\n๐ Performance Characteristics\nMemory Usage: ~1KB per conversation turn\nLookup Time: O(1) for session retrieval\nCleanup Time: O(n) for session limit enforcement\nConcurrency: Thread-safe in-memory operations\n\nThe conversation memory system is designed for production use with efficient memory management and robust error handling.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"","lvl3":""}},
|
|
8469
|
+
{"objectID":"d287e2ebab877225d0b71aafb45118dd2b1d04914f8cf4cd8b2c82b12aba80b8","title":"Conversation Memory","url":"/docs/memory/conversation","content":"Conversation Memory\n\nNeuroLink's Conversation Memory feature enables AI models to maintain context across multiple turns within a session, creating more natural and coherent conversations.\n\n๐ง Overview\n\nThe conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses\nTitle Generation Events: Redis-backed conversations get an AI-generated title, announced with a conversation:titleGenerated event\n\nโ๏ธ Configuration\n\nEnvironment Variables\n\nProgrammatic Configuration\n\n๐ Usage Examples\n\nBasic Usage with Session ID\n\nStreaming Support\n\nThe conversation memory system now fully supports streaming responses with the same memory persistence:\n\nMixed Generate/Stream Conversations\n\nYou can seamlessly mix generate() and stream() calls within the same conversation:\n\nSession Isolation Example\n\n๐ท๏ธ Title Generation Events {#title-generation-events}\n\nWhen a Redis-backed conversation stores its first turn, NeuroLink generates a title for it in the background and saves it on the session (listSessions() reports it). Once the title is stored, the SDK's event emitter fires conversation:titleGenerated.\n\nPayload (ConversationTitleGeneratedEvent):\n\n| Property | Type | Description |\n| ----------- | -------- | ---------------------------------------------------- |\n| sessionId | string | Session the title belongs to |\n| userId | string | User that owns the session (randomUser when unset) |\n| title | string | The title that was stored |\n| timestamp | number | Unix epoch milliseconds when the title was stored |\n\nNotes:\nThe event fires once per conversation, on the first turn, not on later turns.\nOnly Redis-backed memory generates titles; in-memory storage lists sessions by session ID.\nIf the summarization provider cannot answer, the stored title falls back to the first 30 characters of the message plus ..., and the event carries that fallback.\nSet NEUROLINK_TITLE_PROMPT to customize the title prompt. ${userMessage} is replaced with the user's message.\n\n๐ Memory Management\n\nTurn Limits\n\nWhen the number of conversation turns exceeds maxTurnsPerSession, older messages are automatically removed:\n\nSession Limits\n\nWhen the number of active sessions exceeds maxSessions, the least recently used sessions are removed:\n\n๐ API Reference\n\nMemory Statistics\n\nSession Management\n\n๐งช Test Results\n\nThe conversation memory system has been thoroughly tested and validated:\n\nโ
Test Suite Results\n\n| Test Case | Status | Description |\n| --------------------- | ------- | ----------------------------------------------- |\n| Basic Memory | โ
PASS | AI correctly remembers information across turns |\n| Session Isolation | โ
PASS | Sessions remain completely separate |\n| Turn Limits | โ
PASS | Automatic cleanup when limits exceeded |\n| Session Limits | โ
PASS | LRU eviction of old sessions |\n| API Functions | โ
PASS | Clear operations work correctly |\n\nExample Test Output\n\n๐ก Best Practices\nSession ID Strategy\nMemory Limits\nError Handling\n\n๐ง Technical Implementation\n\nArchitecture\n\nMessage Format\n\n๐ Troubleshooting\n\nCommon Issues\n\nMemory not persisting between calls\nEnsure sessionId is consistent across calls\nVerify conversationMemory.enabled is true\nCheck that sessionId is a valid string\n\nPerformance issues with large conversations\nReduce maxTurnsPerSession limit\nImplement session cleanup strategies\nMonitor memory usage statistics\n\nSession isolation not working\nVerify different sessionId values are being used\nCheck for session ID conflicts or duplicates\n\nDebug Logging\n\n๐ Related Documentation\nRedis Conversation Export - Export session history as JSON for analytics\nAPI Reference - Complete SDK documentation\nConfiguration - Environment setup guide\nExamples - More usage examples\nTesting Guide - How to test conversation memory\n\n๐ Performance Characteristics\nMemory Usage: ~1KB per conversation turn\nLookup Time: O(1) for session retrieval\nCleanup Time: O(n) for session limit enforcement\nConcurrency: Thread-safe in-memory operations\n\nThe conversation memory system is designed for production use with efficient memory management and robust error handling.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"","lvl3":""}},
|
|
8470
8470
|
{"objectID":"c5ecb284a686db95e36732c07ddc3b49949d9113b826193e1f6feabf1ae48784","title":"Conversation Memory","url":"/docs/memory/conversation#conversation-memory","content":"NeuroLink's Conversation Memory feature enables AI models to maintain context across multiple turns within a session, creating more natural and coherent conversations.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Conversation Memory","lvl3":""}},
|
|
8471
|
-
{"objectID":"5eb7e9215a286dcd5f45287f758f7c7aa08263f946d3b58182bd9ae2ea029d98","title":"๐ง Overview","url":"/docs/memory/conversation#-overview","content":"The conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"๐ง Overview","lvl3":""}},
|
|
8471
|
+
{"objectID":"5eb7e9215a286dcd5f45287f758f7c7aa08263f946d3b58182bd9ae2ea029d98","title":"๐ง Overview","url":"/docs/memory/conversation#-overview","content":"The conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses\nTitle Generation Events: Redis-backed conversations get an AI-generated title, announced with a conversation:titleGenerated event","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"๐ง Overview","lvl3":""}},
|
|
8472
8472
|
{"objectID":"d2eb5a1a0caa1a4c9a75e15f0cf37e5cd1f37e00d9ef168bac48c0db9cb40ffd","title":"Environment Variables","url":"/docs/memory/conversation#environment-variables","content":"Environment Variables","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Environment Variables","lvl3":""}},
|
|
8473
8473
|
{"objectID":"520e090e02894dc26d3732e6e5710332a0c681ebd3f9648f421d48e01c991d65","title":"Programmatic Configuration","url":"/docs/memory/conversation#programmatic-configuration","content":"Programmatic Configuration","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Programmatic Configuration","lvl3":""}},
|
|
8474
8474
|
{"objectID":"75f91f33db6fd6704adb0d78885dafb7f3d33a0e36ac5edd543ed070cacd2329","title":"Basic Usage with Session ID","url":"/docs/memory/conversation#basic-usage-with-session-id","content":"Basic Usage with Session ID","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Basic Usage with Session ID","lvl3":""}},
|
|
8475
8475
|
{"objectID":"5d65f1e509ac96cb91a4a3027345c19b33198f0e3dd51442e5f3ef4d5e6bf8ba","title":"Streaming Support","url":"/docs/memory/conversation#streaming-support","content":"The conversation memory system now fully supports streaming responses with the same memory persistence:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Streaming Support","lvl3":""}},
|
|
8476
8476
|
{"objectID":"b104538f38fc8e518c4b440d352a6888ccbc0e3fe334446b317e81ef2815ef69","title":"Mixed Generate/Stream Conversations","url":"/docs/memory/conversation#mixed-generatestream-conversations","content":"You can seamlessly mix generate() and stream() calls within the same conversation:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Mixed Generate/Stream Conversations","lvl3":""}},
|
|
8477
8477
|
{"objectID":"3d44a6a1ef6c03c6f48aabb0c9516e1f05d660eac1d51829bfaf2e8506bd9c2e","title":"Session Isolation Example","url":"/docs/memory/conversation#session-isolation-example","content":"Session Isolation Example","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Session Isolation Example","lvl3":""}},
|
|
8478
|
+
{"objectID":"778e79ba226a658a91d70c69514a873920f93d560c695eb75e1d9b6a735567a8","title":"๐ท๏ธ Title Generation Events","url":"/docs/memory/conversation#title-generation-events","content":"When a Redis-backed conversation stores its first turn, NeuroLink generates a title for it in the background and saves it on the session (listSessions() reports it). Once the title is stored, the SDK's event emitter fires conversation:titleGenerated.\n\nPayload (ConversationTitleGeneratedEvent):\n\n| Property | Type | Description |\n| ----------- | -------- | ---------------------------------------------------- |\n| sessionId | string | Session the title belongs to |\n| userId | string | User that owns the session (randomUser when unset) |\n| title | string | The title that was stored |\n| timestamp | number | Unix epoch milliseconds when the title was stored |\n\nNotes:\nThe event fires once per conversation, on the first turn, not on later turns.\nOnly Redis-backed memory generates titles; in-memory storage lists sessions by session ID.\nIf the summarization provider cannot answer, the stored title falls back to the first 30 characters of the message plus ..., and the event carries that fallback.\nSet NEUROLINK_TITLE_PROMPT to customize the title prompt. ${userMessage} is replaced with the user's message.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"๐ท๏ธ Title Generation Events","lvl3":""}},
|
|
8478
8479
|
{"objectID":"63f2feb8c208abf16abfab0606af7eb1d9d51bcbc584182610a3d692a41ef777","title":"Turn Limits","url":"/docs/memory/conversation#turn-limits","content":"When the number of conversation turns exceeds maxTurnsPerSession, older messages are automatically removed:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Turn Limits","lvl3":""}},
|
|
8479
8480
|
{"objectID":"211814691635003dcae6fae6c3c3e7cb5b400ba93b6f4ad45fdec9423659ec0c","title":"Session Limits","url":"/docs/memory/conversation#session-limits","content":"When the number of active sessions exceeds maxSessions, the least recently used sessions are removed:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Session Limits","lvl3":""}},
|
|
8480
8481
|
{"objectID":"11e00a73bb57324fcdab4d4130bf0f98bb4cb3b754b4e558e2feb4474e73a1d3","title":"Memory Statistics","url":"/docs/memory/conversation#memory-statistics","content":"Memory Statistics","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Memory Statistics","lvl3":""}},
|
|
@@ -10349,6 +10350,7 @@
|
|
|
10349
10350
|
{"objectID":"d79631a303031924a7185daa0471458026c9d9ef6bee4a13e49d9ce0610262b9","title":"Event System","url":"/docs/sdk/api-reference#event-system","content":"NeuroLink emits events throughout the generation and streaming lifecycle through a TypedEventEmitter. NeuroLink does not extend EventEmitter itself, so there is no neurolink.on(): get the emitter with getEventEmitter(), subscribe with on() and unsubscribe with off().","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Event System","lvl3":""}},
|
|
10350
10351
|
{"objectID":"357bbb718f458d764e00524826a1d42a64da83167df93a52c04d9ddec3651764","title":"Core Events","url":"/docs/sdk/api-reference#core-events","content":"| Event | Emitted When |\n| ------------------ | ------------------------------------ |\n| generation:start | A generate() call begins |\n| generation:end | A generate() call completes |\n| stream:start | A stream() call begins |\n| stream:chunk | A new chunk arrives during streaming |\n| stream:end | Streaming completes normally |\n| stream:complete | Stream fully consumed |\n| stream:error | An error occurs during streaming |\n| tool:start | A tool execution begins |\n| tool:end | A tool execution completes |\n| response:start | A provider response begins |\n| response:end | A provider response completes |","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Core Events","lvl3":""}},
|
|
10351
10352
|
{"objectID":"efcf19aa651c13dbc72ef4b3d0f83986ee180008a076c0db030509880e4d4b1a","title":"MCP Server Events","url":"/docs/sdk/api-reference#mcp-server-events","content":"| Event | Emitted When |\n| -------------------------------- | ----------------------------------------- |\n| externalMCP:serverConnected | An external MCP server connects |\n| externalMCP:serverDisconnected | An external MCP server disconnects |\n| externalMCP:serverFailed | An external MCP server connection fails |\n| externalMCP:toolDiscovered | A new tool is discovered on an MCP server |\n| externalMCP:toolRemoved | A tool is removed from an MCP server |\n| externalMCP:serverAdded | A new MCP server registration is added |\n| externalMCP:serverRemoved | An MCP server registration is removed |","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"MCP Server Events","lvl3":""}},
|
|
10353
|
+
{"objectID":"e6691df9653e15f2a7a988af6dbe15f86784234b7aa7030fa74880e053d1e262","title":"Conversation Memory Events","url":"/docs/sdk/api-reference#conversation-memory-events","content":"| Event | Emitted When |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| conversation:titleGenerated | A new Redis-backed conversation's title is stored (see Conversation Memory) |","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Conversation Memory Events","lvl3":""}},
|
|
10352
10354
|
{"objectID":"c4d157804d0d96f1d8571e6aabeff4305aca0c07c151894dee3804d611331de6","title":"Other Events","url":"/docs/sdk/api-reference#other-events","content":"| Event | Emitted When |\n| ---------------------- | ----------------------------------- |\n| tools-register:start | Tool registration process begins |\n| tools-register:end | Tool registration process completes |\n| connected | Connection established |\n| message | General message event |\n| error | An error occurs |\n| log | A log message is emitted |\n| log-event | A structured log event is emitted |\n\nTypedEventEmitter Interface:","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Other Events","lvl3":""}},
|
|
10353
10355
|
{"objectID":"7ff1b31f163c4928ce88a79da3c279d1c1c6351ccf3cc5ad2464d2a03174f308","title":"Related Features","url":"/docs/sdk/api-reference#related-features","content":"Human-in-the-Loop (HITL) - Mark tools with requiresConfirmation: true\nGuardrails Middleware - Set middleware per call, in new NeuroLink({ middleware }) or with configureGlobalMiddleware(); add badWords or modelFilter to filter\nConversation History - Use getConversationHistory() method\nMultimodal Chat - Use images array in generate() options\nAuto Evaluation - Enable with enableEvaluation: true\nCLI Loop Sessions - Interactive mode with persistent state\nProvider Orchestration - Set enableOrchestration: true\nRegional Streaming - Use region parameter in generate()\nOffice Documents - Use the files array (or --file) for DOCX, PPTX, XLSX\nPDF Support - Use pdfFiles array for PDF documents\nCSV Support - Use csvFiles array for spreadsheet data\nCLI Commands Reference - CLI equivalents for all SDK methods\nConfiguration Guide - Environment variables and config files\nTroubleshooting - Common SDK issues and solutions\n\nBack to Main README | Next: Visual Demos","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Related Features","lvl3":""}},
|
|
10354
10356
|
{"objectID":"72ff7213f71cd3e590c196c5a1a39a7ab2af152776936e1a647f228cae34de6e","title":"๐ง SDK Custom Tools Guide","url":"/docs/sdk/custom-tools-guide","content":"๐ง SDK Custom Tools Guide\n\nBuild powerful AI applications by extending NeuroLink with your own custom tools.\n\n๐ Overview\n\nNeuroLink's SDK allows you to register custom tools programmatically, giving your AI assistants access to any functionality you need. All registered tools work seamlessly with the built-in tool system across all supported providers.\n\nKey Features\nโ
Type-Safe: Full TypeScript support with Zod schema validation\nโ
Provider Agnostic: Works with all providers that support tools\nโ
Easy Integration: Simple API for tool registration\nโ
Async Support: All tools run asynchronously\nโ
Error Handling: Graceful error handling built-in\n\n๐ Quick Start\n\nBasic Tool Registration\n\nโ ๏ธ Common Mistakes\n\nโ Using schema instead of parameters\n\nโ Using plain JSON schema as parameters\n\nโ
Correct Zod Schema Format\n\n๐ SimpleTool Interface\n\nAll custom tools implement the SimpleTool interface:\n\nInterface Components\ndescription: Clear, actionable description that helps the AI understand when to use the tool\nparameters: Optional Zod schema for validating inputs (highly recommended)\nexecute: Async function that implements the tool's logic\n\n๐ ๏ธ Registration Methods\n\nRegister Single Tool\n\nRegister Multiple Tools\n\nGet Custom Tools\n\n๐ก Common Use Cases\nAPI Integration\nDatabase Operations\nData Processing\nFile Operations\nExternal Service Integration\n\n๐ฏ Best Practices\nClear Descriptions\n\nMake tool descriptions specific and actionable:\nParameter Validation\n\nAlways use Zod schemas for type safety:\nError Handling\n\nHandle errors gracefully:\n\nA returned error is classified as a failure everywhere the SDK reports one,\nexactly as a thrown error is. A result is error-shaped when it carries\nisError: true (the MCP convention), a non-null error field ({ error:\n\"User not found\" }), or a status of \"error\" / \"failed\" / \"failure\" /\n\"fail\". Such a call emits tool:end with success: false and the error\ntext, is stored in session memory as success: false, replays on later turns\nas [called <tool> โ error], and is reported with isError: true in\nresult.toolExecutions. The model still receives the full object you\nreturned โ classification only affects telemetry and memory, never what the\nmodel sees.\nAsync Operations\n\nAll execute functions must return promises:\nTool Naming\n\nUse clear, consistent naming:\n\n๐งช Testing Your Tools\n\nUnit Testing\n\nIntegration Testing\n\n๐ Debugging Tools\n\nEnable Debug Mode\n\nLog Tool Execution\n\n๐ Advanced Patterns\n\nTool Composition\n\nTool Middleware\n\nDynamic Tool Registration\n\nForcing a Tool Call\n\ntoolChoice tells the model whether it must call a tool on a step:\n\n| Value | Effect |\n| --------------------------------- | ------------------------------------------------ |\n| \"auto\" (default) | The model decides whether and which tool to call |\n| \"none\" | No tool calls on any step |\n| \"required\" | The model must call at least one tool |\n| { type: \"tool\", toolName: \"x\" } | The model must call the named tool |\n\nA forced choice (\"required\" or a named tool) is applied only to the first\ntoolChoiceSteps steps of the tool loop โ default 1 โ after which the\nmodel is free to answer. Holding a forced choice on every step would compel\na tool call on every step, and the turn could only end when maxSteps ran\nout. \"auto\" and \"none\" are applied unchanged on every step.\n\nFor anything finer, prepareStep runs before every step and may return a\ntoolChoice for that step, which takes precedence over toolChoiceSteps:\n\nprepareStep receives { stepNumber, steps, maxSteps, model }, where steps\nholds one record per completed step (its text, tool calls โ with input\nalready parsed into an object โ tool results, finish reason and usage,\nincluding prompt-cache tokens where the provider reports them). Only the\nreturned toolChoice is honoured; the legacy model and\nexperimental_activeTools / activeTools fields are accepted for source\ncompatibility but ignored, and their presence is logged once as a warning โ\nuse toolFilter / excludeTools to scope tools. A hook that throws is\nlogged and that step falls back to the toolChoice / toolChoiceSteps rule;\na hook still pending when the turn is aborted or times out is released with\nthe abort. Both toolChoice and prepareStep apply to stream() as well.\n\nVertex, Google AI Studio and Bedrock do not honour toolChoice at all today.\nSageMaker honours tools, toolChoice and prepareStep on generate()\nonly: its stream() sends the prompt without tools.\n\n๐ Performance Considerations\nTimeout Handling\nCaching\nBatch Operations\n\n๐ Security Considerations\n\nInput Sanitization\n\nPermission Checking\n\nRate Limiting\n\n๐ Complete Example\n\nHere's a complete example combining multiple concepts:\n\n๐ MCP Server Integration\n\nBeyond simple tool registration, NeuroLink SDK supports adding complete MCP (Model Context Protocol) servers for more complex tool ecosystems.\n\nAdding I","hierarchy":{"lvl0":"Sdk","lvl1":"๐ง SDK Custom Tools Guide","lvl2":"","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "13.8.
|
|
3
|
+
"version": "13.8.16",
|
|
4
4
|
"packageManager": "pnpm@10.28.2",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types โ generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI ยท Anthropic ยท Gemini ยท Bedrock ยท Azure ยท Ollama ยท TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|