@hashgraphonline/conversational-agent 0.1.204 → 0.1.206

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 (87) hide show
  1. package/dist/cjs/base-agent.d.ts +6 -0
  2. package/dist/cjs/context/ReferenceContextManager.d.ts +84 -0
  3. package/dist/cjs/context/ReferenceResponseProcessor.d.ts +76 -0
  4. package/dist/cjs/conversational-agent.d.ts +34 -0
  5. package/dist/cjs/index.cjs +1 -1
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/langchain-agent.d.ts +1 -0
  8. package/dist/cjs/mcp/ContentProcessor.d.ts +37 -0
  9. package/dist/cjs/mcp/MCPClientManager.d.ts +19 -1
  10. package/dist/cjs/memory/ContentStorage.d.ts +205 -0
  11. package/dist/cjs/memory/MemoryWindow.d.ts +114 -0
  12. package/dist/cjs/memory/ReferenceIdGenerator.d.ts +45 -0
  13. package/dist/cjs/memory/SmartMemoryManager.d.ts +201 -0
  14. package/dist/cjs/memory/TokenCounter.d.ts +61 -0
  15. package/dist/cjs/memory/index.d.ts +7 -0
  16. package/dist/cjs/plugins/hbar-transfer/TransferHbarTool.d.ts +18 -0
  17. package/dist/cjs/services/ContentStoreManager.d.ts +54 -0
  18. package/dist/cjs/types/content-reference.d.ts +213 -0
  19. package/dist/cjs/types/index.d.ts +4 -0
  20. package/dist/esm/index12.js +15 -2
  21. package/dist/esm/index12.js.map +1 -1
  22. package/dist/esm/index14.js +119 -95
  23. package/dist/esm/index14.js.map +1 -1
  24. package/dist/esm/index15.js +159 -114
  25. package/dist/esm/index15.js.map +1 -1
  26. package/dist/esm/index16.js +122 -81
  27. package/dist/esm/index16.js.map +1 -1
  28. package/dist/esm/index17.js +236 -0
  29. package/dist/esm/index17.js.map +1 -0
  30. package/dist/esm/index18.js +95 -0
  31. package/dist/esm/index18.js.map +1 -0
  32. package/dist/esm/index19.js +663 -0
  33. package/dist/esm/index19.js.map +1 -0
  34. package/dist/esm/index2.js +3 -1
  35. package/dist/esm/index2.js.map +1 -1
  36. package/dist/esm/index20.js +233 -0
  37. package/dist/esm/index20.js.map +1 -0
  38. package/dist/esm/index21.js +182 -0
  39. package/dist/esm/index21.js.map +1 -0
  40. package/dist/esm/index22.js +126 -0
  41. package/dist/esm/index22.js.map +1 -0
  42. package/dist/esm/index23.js +68 -0
  43. package/dist/esm/index23.js.map +1 -0
  44. package/dist/esm/index24.js +38 -0
  45. package/dist/esm/index24.js.map +1 -0
  46. package/dist/esm/index6.js +143 -84
  47. package/dist/esm/index6.js.map +1 -1
  48. package/dist/esm/index7.js.map +1 -1
  49. package/dist/esm/index8.js +69 -5
  50. package/dist/esm/index8.js.map +1 -1
  51. package/dist/types/base-agent.d.ts +6 -0
  52. package/dist/types/context/ReferenceContextManager.d.ts +84 -0
  53. package/dist/types/context/ReferenceResponseProcessor.d.ts +76 -0
  54. package/dist/types/conversational-agent.d.ts +34 -0
  55. package/dist/types/langchain-agent.d.ts +1 -0
  56. package/dist/types/mcp/ContentProcessor.d.ts +37 -0
  57. package/dist/types/mcp/MCPClientManager.d.ts +19 -1
  58. package/dist/types/memory/ContentStorage.d.ts +205 -0
  59. package/dist/types/memory/MemoryWindow.d.ts +114 -0
  60. package/dist/types/memory/ReferenceIdGenerator.d.ts +45 -0
  61. package/dist/types/memory/SmartMemoryManager.d.ts +201 -0
  62. package/dist/types/memory/TokenCounter.d.ts +61 -0
  63. package/dist/types/memory/index.d.ts +7 -0
  64. package/dist/types/plugins/hbar-transfer/TransferHbarTool.d.ts +18 -0
  65. package/dist/types/services/ContentStoreManager.d.ts +54 -0
  66. package/dist/types/types/content-reference.d.ts +213 -0
  67. package/dist/types/types/index.d.ts +4 -0
  68. package/package.json +30 -26
  69. package/src/base-agent.ts +6 -0
  70. package/src/context/ReferenceContextManager.ts +345 -0
  71. package/src/context/ReferenceResponseProcessor.ts +296 -0
  72. package/src/conversational-agent.ts +166 -92
  73. package/src/langchain-agent.ts +89 -2
  74. package/src/mcp/ContentProcessor.ts +317 -0
  75. package/src/mcp/MCPClientManager.ts +61 -1
  76. package/src/mcp/adapters/langchain.ts +9 -4
  77. package/src/memory/ContentStorage.ts +954 -0
  78. package/src/memory/MemoryWindow.ts +247 -0
  79. package/src/memory/ReferenceIdGenerator.ts +84 -0
  80. package/src/memory/SmartMemoryManager.ts +323 -0
  81. package/src/memory/TokenCounter.ts +152 -0
  82. package/src/memory/index.ts +8 -0
  83. package/src/plugins/hbar-transfer/TransferHbarTool.ts +19 -1
  84. package/src/plugins/hcs-10/HCS10Plugin.ts +5 -4
  85. package/src/services/ContentStoreManager.ts +199 -0
  86. package/src/types/content-reference.ts +281 -0
  87. package/src/types/index.ts +6 -0
@@ -0,0 +1,247 @@
1
+ import type { BaseMessage } from '@langchain/core/messages';
2
+ import { TokenCounter } from './TokenCounter';
3
+
4
+ /**
5
+ * Result of adding a message to the memory window
6
+ */
7
+ export interface AddMessageResult {
8
+ /** Whether the message was successfully added */
9
+ added: boolean;
10
+ /** Messages that were pruned to make room */
11
+ prunedMessages: BaseMessage[];
12
+ /** Current token count after operation */
13
+ currentTokenCount: number;
14
+ /** Remaining token capacity */
15
+ remainingCapacity: number;
16
+ }
17
+
18
+ /**
19
+ * Memory window that manages conversation history with token-based size limits
20
+ * Automatically prunes old messages to stay within token limits while preserving conversational context
21
+ */
22
+ export class MemoryWindow {
23
+ private messages: BaseMessage[] = [];
24
+ private maxTokens: number;
25
+ private reserveTokens: number;
26
+ private tokenCounter: TokenCounter;
27
+ private systemPrompt: string = '';
28
+ private systemPromptTokens: number = 0;
29
+
30
+ // Default token limits for different model contexts
31
+ public static readonly DEFAULT_MAX_TOKENS = 8000; // Conservative limit for most models
32
+ public static readonly DEFAULT_RESERVE_TOKENS = 1000; // Reserve for response generation
33
+ public static readonly PRUNING_BATCH_SIZE = 2; // Remove messages in pairs to maintain conversation flow
34
+
35
+ constructor(
36
+ maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,
37
+ reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,
38
+ tokenCounter?: TokenCounter
39
+ ) {
40
+ if (reserveTokens >= maxTokens) {
41
+ throw new Error('Reserve tokens must be less than max tokens');
42
+ }
43
+
44
+ this.maxTokens = maxTokens;
45
+ this.reserveTokens = reserveTokens;
46
+ this.tokenCounter = tokenCounter || new TokenCounter();
47
+ }
48
+
49
+ /**
50
+ * Add a message to the memory window, pruning old messages if necessary
51
+ * @param message - The message to add
52
+ * @returns Result of the add operation including any pruned messages
53
+ */
54
+ addMessage(message: BaseMessage): AddMessageResult {
55
+ // Calculate tokens for the new message
56
+ const messageTokens = this.tokenCounter.countMessageTokens(message);
57
+
58
+ // Add the message first
59
+ this.messages.push(message);
60
+
61
+ // Check if we need to prune
62
+ const currentTokens = this.getCurrentTokenCount();
63
+ const availableTokens = this.maxTokens - this.reserveTokens;
64
+
65
+ let prunedMessages: BaseMessage[] = [];
66
+
67
+ if (currentTokens > availableTokens) {
68
+ // Need to prune - remove the new message temporarily
69
+ this.messages.pop();
70
+
71
+ // Prune old messages to make room
72
+ prunedMessages = this.pruneToFit();
73
+
74
+ // Add the new message back
75
+ this.messages.push(message);
76
+ }
77
+
78
+ return {
79
+ added: true,
80
+ prunedMessages,
81
+ currentTokenCount: this.getCurrentTokenCount(),
82
+ remainingCapacity: this.getRemainingTokenCapacity()
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Prune old messages to fit within token limits
88
+ * Removes messages in pairs to maintain conversational flow
89
+ * @returns Array of pruned messages
90
+ */
91
+ pruneToFit(): BaseMessage[] {
92
+ const prunedMessages: BaseMessage[] = [];
93
+ const targetTokens = this.maxTokens - this.reserveTokens;
94
+
95
+ while (this.getCurrentTokenCount() > targetTokens && this.messages.length > 0) {
96
+ // Remove messages in batches to maintain conversation flow
97
+ const batchSize = Math.min(MemoryWindow.PRUNING_BATCH_SIZE, this.messages.length);
98
+
99
+ for (let i = 0; i < batchSize; i++) {
100
+ const prunedMessage = this.messages.shift();
101
+ if (prunedMessage) {
102
+ prunedMessages.push(prunedMessage);
103
+ }
104
+ }
105
+
106
+ // Safety check to prevent infinite loop
107
+ if (prunedMessages.length > 1000) {
108
+ console.warn('MemoryWindow: Excessive pruning detected, stopping to prevent infinite loop');
109
+ break;
110
+ }
111
+ }
112
+
113
+ return prunedMessages;
114
+ }
115
+
116
+ /**
117
+ * Get current token count including system prompt and messages
118
+ * @returns Current token count
119
+ */
120
+ getCurrentTokenCount(): number {
121
+ const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);
122
+ return this.systemPromptTokens + messageTokens;
123
+ }
124
+
125
+ /**
126
+ * Get remaining token capacity before hitting the reserve limit
127
+ * @returns Remaining tokens that can be used
128
+ */
129
+ getRemainingTokenCapacity(): number {
130
+ return Math.max(0, this.maxTokens - this.getCurrentTokenCount());
131
+ }
132
+
133
+ /**
134
+ * Check if a message can be added without exceeding limits
135
+ * @param message - The message to check
136
+ * @returns True if message can be added within reserve limits
137
+ */
138
+ canAddMessage(message: BaseMessage): boolean {
139
+ const messageTokens = this.tokenCounter.countMessageTokens(message);
140
+ const currentTokens = this.getCurrentTokenCount();
141
+ const wouldExceedReserve = (currentTokens + messageTokens) > (this.maxTokens - this.reserveTokens);
142
+
143
+ // Always allow adding if we can prune to make room
144
+ // Only return false if the message itself is larger than our total capacity
145
+ if (messageTokens > this.maxTokens) {
146
+ return false;
147
+ }
148
+
149
+ return !wouldExceedReserve || this.messages.length > 0;
150
+ }
151
+
152
+ /**
153
+ * Get all messages in the memory window
154
+ * @returns Copy of current messages array
155
+ */
156
+ getMessages(): BaseMessage[] {
157
+ return [...this.messages];
158
+ }
159
+
160
+ /**
161
+ * Clear all messages from the memory window
162
+ */
163
+ clear(): void {
164
+ this.messages = [];
165
+ }
166
+
167
+ /**
168
+ * Set the system prompt and update token calculations
169
+ * @param systemPrompt - The system prompt text
170
+ */
171
+ setSystemPrompt(systemPrompt: string): void {
172
+ this.systemPrompt = systemPrompt;
173
+ this.systemPromptTokens = this.tokenCounter.estimateSystemPromptTokens(systemPrompt);
174
+ }
175
+
176
+ /**
177
+ * Get the current system prompt
178
+ * @returns Current system prompt
179
+ */
180
+ getSystemPrompt(): string {
181
+ return this.systemPrompt;
182
+ }
183
+
184
+ /**
185
+ * Get current configuration
186
+ * @returns Memory window configuration
187
+ */
188
+ getConfig() {
189
+ return {
190
+ maxTokens: this.maxTokens,
191
+ reserveTokens: this.reserveTokens,
192
+ currentTokens: this.getCurrentTokenCount(),
193
+ messageCount: this.messages.length,
194
+ systemPromptTokens: this.systemPromptTokens
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Update token limits
200
+ * @param maxTokens - New maximum token limit
201
+ * @param reserveTokens - New reserve token amount
202
+ */
203
+ updateLimits(maxTokens: number, reserveTokens?: number): void {
204
+ if (reserveTokens !== undefined && reserveTokens >= maxTokens) {
205
+ throw new Error('Reserve tokens must be less than max tokens');
206
+ }
207
+
208
+ this.maxTokens = maxTokens;
209
+ if (reserveTokens !== undefined) {
210
+ this.reserveTokens = reserveTokens;
211
+ }
212
+
213
+ // Prune if necessary after updating limits
214
+ if (this.getCurrentTokenCount() > (this.maxTokens - this.reserveTokens)) {
215
+ this.pruneToFit();
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Get statistics about the memory window
221
+ * @returns Memory usage statistics
222
+ */
223
+ getStats() {
224
+ const currentTokens = this.getCurrentTokenCount();
225
+ const capacity = this.maxTokens;
226
+ const usagePercentage = (currentTokens / capacity) * 100;
227
+
228
+ return {
229
+ totalMessages: this.messages.length,
230
+ currentTokens,
231
+ maxTokens: capacity,
232
+ reserveTokens: this.reserveTokens,
233
+ systemPromptTokens: this.systemPromptTokens,
234
+ usagePercentage: Math.round(usagePercentage * 100) / 100,
235
+ remainingCapacity: this.getRemainingTokenCapacity(),
236
+ canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens
237
+ };
238
+ }
239
+
240
+ /**
241
+ * Clean up resources
242
+ */
243
+ dispose(): void {
244
+ this.clear();
245
+ this.tokenCounter.dispose();
246
+ }
247
+ }
@@ -0,0 +1,84 @@
1
+ import { createHash } from 'crypto';
2
+ import { ReferenceId } from '../types/content-reference';
3
+
4
+ /**
5
+ * Content-based reference ID generator using SHA-256 (HCS-1 style)
6
+ *
7
+ * Generates deterministic reference IDs based on content hashing.
8
+ * Same content always produces the same reference ID.
9
+ */
10
+ export class ReferenceIdGenerator {
11
+ /**
12
+ * Generate a content-based reference ID using SHA-256 hashing
13
+ *
14
+ * @param content The content to generate a reference ID for
15
+ * @returns Deterministic reference ID based on content hash
16
+ */
17
+ static generateId(content: Buffer): ReferenceId {
18
+ const hash = createHash('sha256');
19
+ hash.update(content);
20
+ return hash.digest('base64url');
21
+ }
22
+
23
+ /**
24
+ * Validate that a string is a properly formatted reference ID
25
+ *
26
+ * @param id The ID to validate
27
+ * @returns true if the ID is valid format
28
+ */
29
+ static isValidReferenceId(id: string): id is ReferenceId {
30
+ if (!id || typeof id !== 'string') {
31
+ return false;
32
+ }
33
+
34
+ // Check length (base64url encoding of SHA-256 hash = 43 chars)
35
+ if (id.length !== 43) {
36
+ return false;
37
+ }
38
+
39
+ // Check character set (base64url: A-Z, a-z, 0-9, -, _)
40
+ return /^[A-Za-z0-9_-]+$/.test(id);
41
+ }
42
+
43
+ /**
44
+ * Extract reference ID from ref:// format
45
+ *
46
+ * @param input Input string that may contain a reference ID
47
+ * @returns Extracted reference ID or null if not found
48
+ */
49
+ static extractReferenceId(input: string): ReferenceId | null {
50
+ if (!input || typeof input !== 'string') {
51
+ return null;
52
+ }
53
+
54
+ // Check for ref:// format
55
+ const refFormatMatch = input.match(/^ref:\/\/([A-Za-z0-9_-]{43})$/);
56
+ if (refFormatMatch) {
57
+ return refFormatMatch[1] as ReferenceId;
58
+ }
59
+
60
+ // Check if input is directly a valid reference ID
61
+ return this.isValidReferenceId(input) ? input : null;
62
+ }
63
+
64
+ /**
65
+ * Format a reference ID in the standard ref:// format
66
+ *
67
+ * @param referenceId The reference ID to format
68
+ * @returns Formatted reference string
69
+ */
70
+ static formatReference(referenceId: ReferenceId): string {
71
+ return `ref://${referenceId}`;
72
+ }
73
+
74
+ /**
75
+ * Generate a test reference ID (for testing purposes only)
76
+ *
77
+ * @param testSeed A test seed to generate a fake but valid ID format
78
+ * @returns A valid format reference ID for testing
79
+ */
80
+ static generateTestId(testSeed: string): ReferenceId {
81
+ const content = Buffer.from(`test-${testSeed}-${Date.now()}`);
82
+ return this.generateId(content);
83
+ }
84
+ }
@@ -0,0 +1,323 @@
1
+ import type { BaseMessage } from '@langchain/core/messages';
2
+ import { MemoryWindow } from './MemoryWindow';
3
+ import { ContentStorage } from './ContentStorage';
4
+ import { TokenCounter } from './TokenCounter';
5
+
6
+ /**
7
+ * Configuration for SmartMemoryManager
8
+ */
9
+ export interface SmartMemoryConfig {
10
+ /** Maximum tokens for active memory window */
11
+ maxTokens?: number;
12
+ /** Reserve tokens for response generation */
13
+ reserveTokens?: number;
14
+ /** Model name for token counting */
15
+ modelName?: string;
16
+ /** Maximum messages to store in content storage */
17
+ storageLimit?: number;
18
+ }
19
+
20
+ /**
21
+ * Search options for history search
22
+ */
23
+ export interface SearchOptions {
24
+ /** Whether to perform case-sensitive search */
25
+ caseSensitive?: boolean;
26
+ /** Maximum number of results to return */
27
+ limit?: number;
28
+ /** Whether to use regex pattern matching */
29
+ useRegex?: boolean;
30
+ }
31
+
32
+ /**
33
+ * Memory statistics for active memory window
34
+ */
35
+ export interface MemoryStats {
36
+ /** Total active messages in memory window */
37
+ totalActiveMessages: number;
38
+ /** Current token count including system prompt */
39
+ currentTokenCount: number;
40
+ /** Maximum token capacity */
41
+ maxTokens: number;
42
+ /** Remaining token capacity */
43
+ remainingCapacity: number;
44
+ /** System prompt token count */
45
+ systemPromptTokens: number;
46
+ /** Memory usage percentage */
47
+ usagePercentage: number;
48
+ }
49
+
50
+ /**
51
+ * Smart memory manager that combines active memory window with long-term storage
52
+ * Provides context-aware memory management with automatic pruning and searchable history
53
+ */
54
+ export class SmartMemoryManager {
55
+ private memoryWindow: MemoryWindow;
56
+ private contentStorage: ContentStorage;
57
+ private tokenCounter: TokenCounter;
58
+ private config: Required<SmartMemoryConfig>;
59
+
60
+ // Default configuration values
61
+ private static readonly DEFAULT_CONFIG: Required<SmartMemoryConfig> = {
62
+ maxTokens: 8000,
63
+ reserveTokens: 1000,
64
+ modelName: 'gpt-4o',
65
+ storageLimit: 1000
66
+ };
67
+
68
+ constructor(config: SmartMemoryConfig = {}) {
69
+ this.config = { ...SmartMemoryManager.DEFAULT_CONFIG, ...config };
70
+
71
+ // Initialize components
72
+ this.tokenCounter = new TokenCounter(this.config.modelName as any);
73
+ this.contentStorage = new ContentStorage(this.config.storageLimit);
74
+ this.memoryWindow = new MemoryWindow(
75
+ this.config.maxTokens,
76
+ this.config.reserveTokens,
77
+ this.tokenCounter
78
+ );
79
+ }
80
+
81
+ /**
82
+ * Add a message to the active memory window
83
+ * Automatically handles pruning and storage of displaced messages
84
+ * @param message - Message to add
85
+ */
86
+ addMessage(message: BaseMessage): void {
87
+ const result = this.memoryWindow.addMessage(message);
88
+
89
+ // Store any pruned messages in content storage
90
+ if (result.prunedMessages.length > 0) {
91
+ this.contentStorage.storeMessages(result.prunedMessages);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Get all active messages from the memory window
97
+ * @returns Array of active messages in chronological order
98
+ */
99
+ getMessages(): BaseMessage[] {
100
+ return this.memoryWindow.getMessages();
101
+ }
102
+
103
+ /**
104
+ * Clear active memory window
105
+ * @param clearStorage - Whether to also clear the content storage (default: false)
106
+ */
107
+ clear(clearStorage: boolean = false): void {
108
+ this.memoryWindow.clear();
109
+
110
+ if (clearStorage) {
111
+ this.contentStorage.clear();
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Set the system prompt for the memory window
117
+ * @param systemPrompt - System prompt text
118
+ */
119
+ setSystemPrompt(systemPrompt: string): void {
120
+ this.memoryWindow.setSystemPrompt(systemPrompt);
121
+ }
122
+
123
+ /**
124
+ * Get the current system prompt
125
+ * @returns Current system prompt text
126
+ */
127
+ getSystemPrompt(): string {
128
+ return this.memoryWindow.getSystemPrompt();
129
+ }
130
+
131
+ /**
132
+ * Search through stored message history
133
+ * @param query - Search term or pattern
134
+ * @param options - Search configuration
135
+ * @returns Array of matching messages from history
136
+ */
137
+ searchHistory(query: string, options: SearchOptions = {}): BaseMessage[] {
138
+ return this.contentStorage.searchMessages(query, options);
139
+ }
140
+
141
+ /**
142
+ * Get recent messages from storage history
143
+ * @param count - Number of recent messages to retrieve
144
+ * @returns Array of recent messages from storage
145
+ */
146
+ getRecentHistory(count: number): BaseMessage[] {
147
+ return this.contentStorage.getRecentMessages(count);
148
+ }
149
+
150
+ /**
151
+ * Check if a message can be added without exceeding limits
152
+ * @param message - Message to test
153
+ * @returns True if message can be added
154
+ */
155
+ canAddMessage(message: BaseMessage): boolean {
156
+ return this.memoryWindow.canAddMessage(message);
157
+ }
158
+
159
+ /**
160
+ * Get statistics about the active memory window
161
+ * @returns Memory usage statistics
162
+ */
163
+ getMemoryStats(): MemoryStats {
164
+ const windowStats = this.memoryWindow.getStats();
165
+
166
+ return {
167
+ totalActiveMessages: windowStats.totalMessages,
168
+ currentTokenCount: windowStats.currentTokens,
169
+ maxTokens: windowStats.maxTokens,
170
+ remainingCapacity: windowStats.remainingCapacity,
171
+ systemPromptTokens: windowStats.systemPromptTokens,
172
+ usagePercentage: windowStats.usagePercentage
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Get statistics about the content storage
178
+ * @returns Storage usage statistics
179
+ */
180
+ getStorageStats() {
181
+ return this.contentStorage.getStorageStats();
182
+ }
183
+
184
+ /**
185
+ * Get combined statistics for both active memory and storage
186
+ * @returns Combined memory and storage statistics
187
+ */
188
+ getOverallStats() {
189
+ const memoryStats = this.getMemoryStats();
190
+ const storageStats = this.getStorageStats();
191
+
192
+ return {
193
+ activeMemory: memoryStats,
194
+ storage: storageStats,
195
+ totalMessagesManaged: memoryStats.totalActiveMessages + storageStats.totalMessages,
196
+ activeMemoryUtilization: memoryStats.usagePercentage,
197
+ storageUtilization: storageStats.usagePercentage
198
+ };
199
+ }
200
+
201
+ /**
202
+ * Update the configuration and apply changes
203
+ * @param newConfig - New configuration options
204
+ */
205
+ updateConfig(newConfig: Partial<SmartMemoryConfig>): void {
206
+ this.config = { ...this.config, ...newConfig };
207
+
208
+ // Update components with new configuration
209
+ if (newConfig.maxTokens !== undefined || newConfig.reserveTokens !== undefined) {
210
+ this.memoryWindow.updateLimits(
211
+ this.config.maxTokens,
212
+ this.config.reserveTokens
213
+ );
214
+ }
215
+
216
+ if (newConfig.storageLimit !== undefined) {
217
+ this.contentStorage.updateStorageLimit(this.config.storageLimit);
218
+ }
219
+
220
+ // Note: Model name changes would require recreating the token counter
221
+ // This is not implemented to avoid disrupting ongoing operations
222
+ }
223
+
224
+ /**
225
+ * Get current configuration
226
+ * @returns Current configuration settings
227
+ */
228
+ getConfig(): Required<SmartMemoryConfig> {
229
+ return { ...this.config };
230
+ }
231
+
232
+ /**
233
+ * Get messages from storage within a time range
234
+ * @param startTime - Start of time range
235
+ * @param endTime - End of time range
236
+ * @returns Messages within the specified time range
237
+ */
238
+ getHistoryFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {
239
+ return this.contentStorage.getMessagesFromTimeRange(startTime, endTime);
240
+ }
241
+
242
+ /**
243
+ * Get messages from storage by message type
244
+ * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)
245
+ * @param limit - Maximum number of messages to return
246
+ * @returns Messages of the specified type
247
+ */
248
+ getHistoryByType(messageType: string, limit?: number): BaseMessage[] {
249
+ return this.contentStorage.getMessagesByType(messageType, limit);
250
+ }
251
+
252
+ /**
253
+ * Get recent messages from storage within the last N minutes
254
+ * @param minutes - Number of minutes to look back
255
+ * @returns Messages from the last N minutes
256
+ */
257
+ getRecentHistoryByTime(minutes: number): BaseMessage[] {
258
+ return this.contentStorage.getRecentMessagesByTime(minutes);
259
+ }
260
+
261
+ /**
262
+ * Export the current state for persistence or analysis
263
+ * @returns Serializable representation of memory state
264
+ */
265
+ exportState() {
266
+ return {
267
+ config: this.config,
268
+ activeMessages: this.memoryWindow.getMessages().map(msg => ({
269
+ content: msg.content,
270
+ type: msg._getType()
271
+ })),
272
+ systemPrompt: this.memoryWindow.getSystemPrompt(),
273
+ memoryStats: this.getMemoryStats(),
274
+ storageStats: this.getStorageStats(),
275
+ storedMessages: this.contentStorage.exportMessages()
276
+ };
277
+ }
278
+
279
+ /**
280
+ * Get a summary of conversation context for external use
281
+ * Useful for providing context to other systems or for logging
282
+ * @param includeStoredContext - Whether to include recent stored messages
283
+ * @returns Context summary object
284
+ */
285
+ getContextSummary(includeStoredContext: boolean = false) {
286
+ const activeMessages = this.getMessages();
287
+ const summary = {
288
+ activeMessageCount: activeMessages.length,
289
+ systemPrompt: this.getSystemPrompt(),
290
+ recentMessages: activeMessages.slice(-5), // Last 5 active messages
291
+ memoryUtilization: this.getMemoryStats().usagePercentage,
292
+ hasStoredHistory: this.getStorageStats().totalMessages > 0
293
+ };
294
+
295
+ if (includeStoredContext) {
296
+ return {
297
+ ...summary,
298
+ recentStoredMessages: this.getRecentHistory(10), // Last 10 stored messages
299
+ storageStats: this.getStorageStats()
300
+ };
301
+ }
302
+
303
+ return summary;
304
+ }
305
+
306
+ /**
307
+ * Perform maintenance operations
308
+ * Optimizes storage and cleans up resources
309
+ */
310
+ performMaintenance(): void {
311
+ // No specific maintenance needed currently
312
+ // This method is reserved for future optimizations
313
+ }
314
+
315
+ /**
316
+ * Clean up resources and dispose of components
317
+ */
318
+ dispose(): void {
319
+ this.memoryWindow.dispose();
320
+ this.contentStorage.dispose();
321
+ this.tokenCounter.dispose();
322
+ }
323
+ }