@hashgraphonline/conversational-agent 0.1.208 → 0.1.209

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 (68) hide show
  1. package/dist/cjs/conversational-agent.d.ts +67 -8
  2. package/dist/cjs/index.cjs +1 -1
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs/index.d.ts +1 -0
  5. package/dist/cjs/langchain-agent.d.ts +8 -0
  6. package/dist/cjs/memory/SmartMemoryManager.d.ts +58 -21
  7. package/dist/cjs/memory/index.d.ts +1 -1
  8. package/dist/esm/index.js +8 -0
  9. package/dist/esm/index.js.map +1 -1
  10. package/dist/esm/index12.js +124 -46
  11. package/dist/esm/index12.js.map +1 -1
  12. package/dist/esm/index13.js +178 -13
  13. package/dist/esm/index13.js.map +1 -1
  14. package/dist/esm/index14.js +604 -100
  15. package/dist/esm/index14.js.map +1 -1
  16. package/dist/esm/index15.js +464 -9
  17. package/dist/esm/index15.js.map +1 -1
  18. package/dist/esm/index16.js +44 -172
  19. package/dist/esm/index16.js.map +1 -1
  20. package/dist/esm/index17.js +11 -156
  21. package/dist/esm/index17.js.map +1 -1
  22. package/dist/esm/index18.js +106 -191
  23. package/dist/esm/index18.js.map +1 -1
  24. package/dist/esm/index19.js +9 -660
  25. package/dist/esm/index19.js.map +1 -1
  26. package/dist/esm/index2.js +22 -13
  27. package/dist/esm/index2.js.map +1 -1
  28. package/dist/esm/index20.js +150 -206
  29. package/dist/esm/index20.js.map +1 -1
  30. package/dist/esm/index21.js +140 -166
  31. package/dist/esm/index21.js.map +1 -1
  32. package/dist/esm/index22.js +47 -105
  33. package/dist/esm/index22.js.map +1 -1
  34. package/dist/esm/index23.js +24 -89
  35. package/dist/esm/index23.js.map +1 -1
  36. package/dist/esm/index24.js +83 -56
  37. package/dist/esm/index24.js.map +1 -1
  38. package/dist/esm/index25.js +236 -32
  39. package/dist/esm/index25.js.map +1 -1
  40. package/dist/esm/index5.js +1 -1
  41. package/dist/esm/index6.js +295 -17
  42. package/dist/esm/index6.js.map +1 -1
  43. package/dist/esm/index8.js +82 -8
  44. package/dist/esm/index8.js.map +1 -1
  45. package/dist/types/conversational-agent.d.ts +67 -8
  46. package/dist/types/index.d.ts +1 -0
  47. package/dist/types/langchain-agent.d.ts +8 -0
  48. package/dist/types/memory/SmartMemoryManager.d.ts +58 -21
  49. package/dist/types/memory/index.d.ts +1 -1
  50. package/package.json +3 -3
  51. package/src/context/ReferenceContextManager.ts +9 -4
  52. package/src/context/ReferenceResponseProcessor.ts +3 -4
  53. package/src/conversational-agent.ts +379 -31
  54. package/src/index.ts +2 -0
  55. package/src/langchain/ContentAwareAgentExecutor.ts +0 -1
  56. package/src/langchain-agent.ts +94 -11
  57. package/src/mcp/ContentProcessor.ts +13 -3
  58. package/src/mcp/adapters/langchain.ts +1 -9
  59. package/src/memory/ContentStorage.ts +3 -51
  60. package/src/memory/MemoryWindow.ts +4 -16
  61. package/src/memory/ReferenceIdGenerator.ts +0 -4
  62. package/src/memory/SmartMemoryManager.ts +400 -33
  63. package/src/memory/TokenCounter.ts +12 -16
  64. package/src/memory/index.ts +1 -1
  65. package/src/plugins/hcs-10/HCS10Plugin.ts +44 -14
  66. package/src/services/ContentStoreManager.ts +0 -3
  67. package/src/types/content-reference.ts +8 -8
  68. package/src/types/index.ts +0 -1
@@ -1,151 +1,655 @@
1
- import { ContentStorage } from "./index19.js";
2
- import { ContentStoreService, ContentResolverRegistry, shouldUseReference, extractReferenceId } from "@hashgraphonline/standards-sdk";
3
- class ContentStorageAdapter {
4
- constructor(storage) {
5
- this.storage = storage;
1
+ import { ReferenceIdGenerator } from "./index22.js";
2
+ import { DEFAULT_CONTENT_REFERENCE_CONFIG, ContentReferenceError } from "./index23.js";
3
+ const _ContentStorage = class _ContentStorage {
4
+ constructor(maxStorage = _ContentStorage.DEFAULT_MAX_STORAGE, referenceConfig) {
5
+ this.messages = [];
6
+ this.idCounter = 0;
7
+ this.contentStore = /* @__PURE__ */ new Map();
8
+ this.maxStorage = maxStorage;
9
+ this.referenceConfig = { ...DEFAULT_CONTENT_REFERENCE_CONFIG, ...referenceConfig };
10
+ this.referenceStats = {
11
+ activeReferences: 0,
12
+ totalStorageBytes: 0,
13
+ recentlyCleanedUp: 0,
14
+ totalResolutions: 0,
15
+ failedResolutions: 0,
16
+ averageContentSize: 0,
17
+ storageUtilization: 0,
18
+ performanceMetrics: {
19
+ averageCreationTimeMs: 0,
20
+ averageResolutionTimeMs: 0,
21
+ averageCleanupTimeMs: 0,
22
+ creationTimes: [],
23
+ resolutionTimes: [],
24
+ cleanupTimes: []
25
+ }
26
+ };
27
+ if (this.referenceConfig.enableAutoCleanup) {
28
+ this.startReferenceCleanupTimer();
29
+ }
6
30
  }
7
- async storeContent(content, metadata) {
8
- const contentRef = await this.storage.storeContent(content, metadata);
9
- return contentRef.referenceId;
31
+ /**
32
+ * Store messages in the content storage
33
+ * Automatically drops oldest messages if storage limit is exceeded
34
+ * @param messages - Messages to store
35
+ * @returns Result indicating how many messages were stored and dropped
36
+ */
37
+ storeMessages(messages) {
38
+ if (messages.length === 0) {
39
+ return { stored: 0, dropped: 0 };
40
+ }
41
+ const now = /* @__PURE__ */ new Date();
42
+ let dropped = 0;
43
+ const storedMessages = messages.map((message) => ({
44
+ message,
45
+ storedAt: now,
46
+ id: this.generateId()
47
+ }));
48
+ this.messages.push(...storedMessages);
49
+ while (this.messages.length > this.maxStorage) {
50
+ this.messages.shift();
51
+ dropped++;
52
+ }
53
+ return {
54
+ stored: storedMessages.length,
55
+ dropped
56
+ };
10
57
  }
11
- async resolveReference(referenceId) {
12
- const result = await this.storage.resolveReference(referenceId);
13
- if (result.success && result.content) {
14
- const response = {
15
- content: result.content
16
- };
17
- if (result.metadata) {
18
- response.metadata = {
19
- ...result.metadata.mimeType !== void 0 && { mimeType: result.metadata.mimeType },
20
- ...result.metadata.fileName !== void 0 && { fileName: result.metadata.fileName },
21
- originalSize: result.metadata.sizeBytes
22
- };
58
+ /**
59
+ * Get the most recent messages from storage
60
+ * @param count - Number of recent messages to retrieve
61
+ * @returns Array of recent messages in chronological order
62
+ */
63
+ getRecentMessages(count) {
64
+ if (count <= 0 || this.messages.length === 0) {
65
+ return [];
66
+ }
67
+ const startIndex = Math.max(0, this.messages.length - count);
68
+ return this.messages.slice(startIndex).map((stored) => stored.message);
69
+ }
70
+ /**
71
+ * Search for messages containing specific text or patterns
72
+ * @param query - Search term or regex pattern
73
+ * @param options - Search configuration options
74
+ * @returns Array of matching messages
75
+ */
76
+ searchMessages(query, options = {}) {
77
+ if (!query || this.messages.length === 0) {
78
+ return [];
79
+ }
80
+ const {
81
+ caseSensitive = false,
82
+ limit,
83
+ useRegex = false
84
+ } = options;
85
+ let matches = [];
86
+ if (useRegex) {
87
+ try {
88
+ const regex = new RegExp(query, caseSensitive ? "g" : "gi");
89
+ matches = this.messages.filter((stored) => regex.test(stored.message.content)).map((stored) => stored.message);
90
+ } catch (error) {
91
+ console.warn("Invalid regex pattern:", query, error);
92
+ return [];
23
93
  }
24
- return response;
25
94
  } else {
26
- throw new Error(result.error || "Reference not found");
95
+ const searchTerm = caseSensitive ? query : query.toLowerCase();
96
+ matches = this.messages.filter((stored) => {
97
+ const content = stored.message.content;
98
+ const searchContent = caseSensitive ? content : content.toLowerCase();
99
+ return searchContent.includes(searchTerm);
100
+ }).map((stored) => stored.message);
27
101
  }
102
+ return limit ? matches.slice(0, limit) : matches;
28
103
  }
29
- async hasReference(referenceId) {
30
- return await this.storage.hasReference(referenceId);
104
+ /**
105
+ * Get messages from a specific time range
106
+ * @param startTime - Start of time range (inclusive)
107
+ * @param endTime - End of time range (inclusive)
108
+ * @returns Array of messages within the time range
109
+ */
110
+ getMessagesFromTimeRange(startTime, endTime) {
111
+ if (startTime > endTime || this.messages.length === 0) {
112
+ return [];
113
+ }
114
+ return this.messages.filter(
115
+ (stored) => stored.storedAt >= startTime && stored.storedAt <= endTime
116
+ ).map((stored) => stored.message);
31
117
  }
32
- async cleanupReference(referenceId) {
33
- await this.storage.cleanupReference(referenceId);
118
+ /**
119
+ * Get storage statistics and usage information
120
+ * @returns Current storage statistics
121
+ */
122
+ getStorageStats() {
123
+ const totalMessages = this.messages.length;
124
+ const usagePercentage = totalMessages > 0 ? Math.round(totalMessages / this.maxStorage * 100) : 0;
125
+ let oldestMessageTime;
126
+ let newestMessageTime;
127
+ if (totalMessages > 0) {
128
+ oldestMessageTime = this.messages[0].storedAt;
129
+ newestMessageTime = this.messages[totalMessages - 1].storedAt;
130
+ }
131
+ return {
132
+ totalMessages,
133
+ maxStorageLimit: this.maxStorage,
134
+ usagePercentage,
135
+ oldestMessageTime,
136
+ newestMessageTime
137
+ };
34
138
  }
35
- async getStats() {
36
- return await this.storage.getStats();
139
+ /**
140
+ * Clear all stored messages
141
+ */
142
+ clear() {
143
+ this.messages = [];
144
+ this.idCounter = 0;
37
145
  }
38
- async updateConfig(config) {
39
- return await this.storage.updateConfig(config);
146
+ /**
147
+ * Get total number of stored messages
148
+ * @returns Number of messages currently in storage
149
+ */
150
+ getTotalStoredMessages() {
151
+ return this.messages.length;
40
152
  }
41
- async performCleanup() {
42
- await this.storage.performCleanup();
153
+ /**
154
+ * Update the maximum storage limit
155
+ * @param newLimit - New maximum storage limit
156
+ */
157
+ updateStorageLimit(newLimit) {
158
+ if (newLimit <= 0) {
159
+ throw new Error("Storage limit must be greater than 0");
160
+ }
161
+ this.maxStorage = newLimit;
162
+ while (this.messages.length > this.maxStorage) {
163
+ this.messages.shift();
164
+ }
43
165
  }
44
- async dispose() {
45
- return Promise.resolve(this.storage.dispose());
166
+ /**
167
+ * Get messages by message type
168
+ * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)
169
+ * @param limit - Maximum number of messages to return
170
+ * @returns Array of messages of the specified type
171
+ */
172
+ getMessagesByType(messageType, limit) {
173
+ const filtered = this.messages.filter((stored) => stored.message._getType() === messageType).map((stored) => stored.message);
174
+ return limit ? filtered.slice(0, limit) : filtered;
175
+ }
176
+ /**
177
+ * Get the current storage configuration
178
+ * @returns Storage configuration object
179
+ */
180
+ getConfig() {
181
+ return {
182
+ maxStorage: this.maxStorage,
183
+ currentUsage: this.messages.length,
184
+ utilizationPercentage: this.messages.length / this.maxStorage * 100
185
+ };
46
186
  }
47
- }
48
- class ContentResolver {
49
- constructor(adapter) {
50
- this.adapter = adapter;
187
+ /**
188
+ * Generate a unique ID for stored messages
189
+ * @returns Unique string identifier
190
+ */
191
+ generateId() {
192
+ return `msg_${++this.idCounter}_${Date.now()}`;
51
193
  }
52
- async resolveReference(referenceId) {
53
- return await this.adapter.resolveReference(referenceId);
194
+ /**
195
+ * Get messages stored within the last N minutes
196
+ * @param minutes - Number of minutes to look back
197
+ * @returns Array of messages from the last N minutes
198
+ */
199
+ getRecentMessagesByTime(minutes) {
200
+ if (minutes <= 0 || this.messages.length === 0) {
201
+ return [];
202
+ }
203
+ const cutoffTime = new Date(Date.now() - minutes * 60 * 1e3);
204
+ return this.messages.filter((stored) => stored.storedAt >= cutoffTime).map((stored) => stored.message);
54
205
  }
206
+ /**
207
+ * Export messages to a JSON-serializable format
208
+ * @returns Serializable representation of stored messages
209
+ */
210
+ exportMessages() {
211
+ return this.messages.map((stored) => ({
212
+ content: stored.message.content,
213
+ type: stored.message._getType(),
214
+ storedAt: stored.storedAt.toISOString(),
215
+ id: stored.id
216
+ }));
217
+ }
218
+ /**
219
+ * Determine if content should be stored as a reference based on size
220
+ */
55
221
  shouldUseReference(content) {
56
- return shouldUseReference(content);
57
- }
58
- extractReferenceId(input) {
59
- return extractReferenceId(input);
60
- }
61
- }
62
- class ContentStoreManager {
63
- constructor(maxMessageStorage = 1e3, referenceConfig, logger) {
64
- this.isRegistered = false;
65
- this.logger = logger || {
66
- info: console.log,
67
- debug: console.log,
68
- warn: console.warn,
69
- error: console.error
70
- };
71
- this.contentStorage = new ContentStorage(maxMessageStorage, referenceConfig);
72
- this.adapter = new ContentStorageAdapter(this.contentStorage);
73
- this.resolver = new ContentResolver(this.adapter);
222
+ const size = Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content, "utf8");
223
+ return size > this.referenceConfig.sizeThresholdBytes;
74
224
  }
75
225
  /**
76
- * Initialize and register content storage for cross-package access
226
+ * Store content and return a reference if it exceeds the size threshold
227
+ * Otherwise returns null to indicate direct content should be used
77
228
  */
78
- async initialize() {
79
- if (this.isRegistered) {
80
- this.logger.warn("ContentStoreManager is already initialized");
81
- return;
229
+ async storeContentIfLarge(content, metadata) {
230
+ const buffer = Buffer.isBuffer(content) ? content : Buffer.from(content, "utf8");
231
+ if (!this.shouldUseReference(buffer)) {
232
+ return null;
233
+ }
234
+ const storeMetadata = {
235
+ contentType: metadata.contentType || this.detectContentType(buffer, metadata.mimeType),
236
+ sizeBytes: buffer.length,
237
+ source: metadata.source,
238
+ tags: []
239
+ };
240
+ if (metadata.mimeType !== void 0) {
241
+ storeMetadata.mimeType = metadata.mimeType;
242
+ }
243
+ if (metadata.mcpToolName !== void 0) {
244
+ storeMetadata.mcpToolName = metadata.mcpToolName;
245
+ }
246
+ if (metadata.fileName !== void 0) {
247
+ storeMetadata.fileName = metadata.fileName;
82
248
  }
249
+ if (metadata.tags !== void 0) {
250
+ storeMetadata.tags = metadata.tags;
251
+ }
252
+ if (metadata.customMetadata !== void 0) {
253
+ storeMetadata.customMetadata = metadata.customMetadata;
254
+ }
255
+ return await this.storeContent(buffer, storeMetadata);
256
+ }
257
+ /**
258
+ * Store content and return a reference (implements ContentReferenceStore)
259
+ */
260
+ async storeContent(content, metadata) {
261
+ const startTime = Date.now();
83
262
  try {
84
- await ContentStoreService.setInstance(this.adapter);
85
- ContentResolverRegistry.register(this.resolver);
86
- this.isRegistered = true;
87
- this.logger.info("ContentStoreManager initialized and registered for cross-package access");
263
+ const now = /* @__PURE__ */ new Date();
264
+ const referenceId = ReferenceIdGenerator.generateId(content);
265
+ const fullMetadata = {
266
+ ...metadata,
267
+ createdAt: now,
268
+ lastAccessedAt: now,
269
+ accessCount: 0
270
+ };
271
+ const storedContent = {
272
+ content,
273
+ metadata: fullMetadata,
274
+ state: "active"
275
+ };
276
+ const expirationTime = this.calculateExpirationTime(metadata.source);
277
+ if (expirationTime !== void 0) {
278
+ storedContent.expiresAt = expirationTime;
279
+ }
280
+ this.contentStore.set(referenceId, storedContent);
281
+ this.updateStatsAfterStore(content.length);
282
+ await this.enforceReferenceStorageLimits();
283
+ const preview = this.createContentPreview(content, fullMetadata.contentType);
284
+ const referenceMetadata = {
285
+ contentType: fullMetadata.contentType,
286
+ sizeBytes: fullMetadata.sizeBytes,
287
+ source: fullMetadata.source
288
+ };
289
+ if (fullMetadata.fileName !== void 0) {
290
+ referenceMetadata.fileName = fullMetadata.fileName;
291
+ }
292
+ if (fullMetadata.mimeType !== void 0) {
293
+ referenceMetadata.mimeType = fullMetadata.mimeType;
294
+ }
295
+ const reference = {
296
+ referenceId,
297
+ state: "active",
298
+ preview,
299
+ metadata: referenceMetadata,
300
+ createdAt: now,
301
+ format: "ref://{id}"
302
+ };
303
+ const duration = Date.now() - startTime;
304
+ this.recordPerformanceMetric("creation", duration);
305
+ return reference;
88
306
  } catch (error) {
89
- this.logger.error("Failed to initialize ContentStoreManager:", error);
90
- throw error;
307
+ const duration = Date.now() - startTime;
308
+ this.recordPerformanceMetric("creation", duration);
309
+ console.error("[ContentStorage] Failed to store content:", error);
310
+ throw new ContentReferenceError(
311
+ `Failed to store content: ${error instanceof Error ? error.message : "Unknown error"}`,
312
+ "system_error",
313
+ void 0,
314
+ ["Try again", "Check storage limits", "Contact administrator"]
315
+ );
91
316
  }
92
317
  }
93
318
  /**
94
- * Get the underlying ContentStorage instance
319
+ * Resolve a reference to its content (implements ContentReferenceStore)
95
320
  */
96
- getContentStorage() {
97
- return this.contentStorage;
321
+ async resolveReference(referenceId) {
322
+ const startTime = Date.now();
323
+ try {
324
+ if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {
325
+ this.referenceStats.failedResolutions++;
326
+ return {
327
+ success: false,
328
+ error: "Invalid reference ID format",
329
+ errorType: "not_found",
330
+ suggestedActions: ["Check the reference ID format", "Ensure the reference ID is complete"]
331
+ };
332
+ }
333
+ const storedContent = this.contentStore.get(referenceId);
334
+ if (!storedContent) {
335
+ this.referenceStats.failedResolutions++;
336
+ return {
337
+ success: false,
338
+ error: "Reference not found",
339
+ errorType: "not_found",
340
+ suggestedActions: ["Verify the reference ID", "Check if the content has expired", "Request fresh content"]
341
+ };
342
+ }
343
+ if (storedContent.expiresAt && storedContent.expiresAt < /* @__PURE__ */ new Date()) {
344
+ storedContent.state = "expired";
345
+ this.referenceStats.failedResolutions++;
346
+ return {
347
+ success: false,
348
+ error: "Reference has expired",
349
+ errorType: "expired",
350
+ suggestedActions: ["Request fresh content", "Use alternative content source"]
351
+ };
352
+ }
353
+ if (storedContent.state !== "active") {
354
+ this.referenceStats.failedResolutions++;
355
+ return {
356
+ success: false,
357
+ error: `Reference is ${storedContent.state}`,
358
+ errorType: storedContent.state === "expired" ? "expired" : "corrupted",
359
+ suggestedActions: ["Request fresh content", "Check reference validity"]
360
+ };
361
+ }
362
+ storedContent.metadata.lastAccessedAt = /* @__PURE__ */ new Date();
363
+ storedContent.metadata.accessCount++;
364
+ this.referenceStats.totalResolutions++;
365
+ const duration = Date.now() - startTime;
366
+ this.recordPerformanceMetric("resolution", duration);
367
+ return {
368
+ success: true,
369
+ content: storedContent.content,
370
+ metadata: storedContent.metadata
371
+ };
372
+ } catch (error) {
373
+ const duration = Date.now() - startTime;
374
+ this.recordPerformanceMetric("resolution", duration);
375
+ this.referenceStats.failedResolutions++;
376
+ console.error(`[ContentStorage] Error resolving reference ${referenceId}:`, error);
377
+ return {
378
+ success: false,
379
+ error: `System error resolving reference: ${error instanceof Error ? error.message : "Unknown error"}`,
380
+ errorType: "system_error",
381
+ suggestedActions: ["Try again", "Contact administrator"]
382
+ };
383
+ }
98
384
  }
99
385
  /**
100
- * Get storage statistics
386
+ * Check if a reference exists and is valid
101
387
  */
102
- async getStats() {
103
- return await this.contentStorage.getStats();
388
+ async hasReference(referenceId) {
389
+ if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {
390
+ return false;
391
+ }
392
+ const storedContent = this.contentStore.get(referenceId);
393
+ if (!storedContent) {
394
+ return false;
395
+ }
396
+ if (storedContent.expiresAt && storedContent.expiresAt < /* @__PURE__ */ new Date()) {
397
+ storedContent.state = "expired";
398
+ return false;
399
+ }
400
+ return storedContent.state === "active";
104
401
  }
105
402
  /**
106
- * Update configuration
403
+ * Mark a reference for cleanup
107
404
  */
108
- async updateConfig(config) {
109
- return await this.contentStorage.updateConfig(config);
405
+ async cleanupReference(referenceId) {
406
+ const storedContent = this.contentStore.get(referenceId);
407
+ if (!storedContent) {
408
+ return false;
409
+ }
410
+ this.referenceStats.totalStorageBytes -= storedContent.content.length;
411
+ this.referenceStats.activeReferences--;
412
+ this.referenceStats.recentlyCleanedUp++;
413
+ this.contentStore.delete(referenceId);
414
+ return true;
110
415
  }
111
416
  /**
112
- * Perform manual cleanup
417
+ * Get current reference storage statistics (implements ContentReferenceStore)
113
418
  */
114
- async performCleanup() {
115
- return await this.contentStorage.performCleanup();
419
+ async getStats() {
420
+ this.updateReferenceStorageStats();
421
+ return {
422
+ ...this.referenceStats,
423
+ performanceMetrics: {
424
+ averageCreationTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.creationTimes),
425
+ averageResolutionTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.resolutionTimes),
426
+ averageCleanupTimeMs: this.calculateAverage(this.referenceStats.performanceMetrics.cleanupTimes)
427
+ }
428
+ };
116
429
  }
117
430
  /**
118
- * Check if content should be stored as reference
431
+ * Update reference configuration
119
432
  */
120
- shouldUseReference(content) {
121
- return this.contentStorage.shouldUseReference(content);
433
+ async updateConfig(config) {
434
+ this.referenceConfig = { ...this.referenceConfig, ...config };
435
+ if (this.cleanupTimer) {
436
+ clearInterval(this.cleanupTimer);
437
+ delete this.cleanupTimer;
438
+ }
439
+ if (this.referenceConfig.enableAutoCleanup) {
440
+ this.startReferenceCleanupTimer();
441
+ }
122
442
  }
123
443
  /**
124
- * Store content if it's large enough
444
+ * Perform cleanup based on current policies (implements ContentReferenceStore)
125
445
  */
126
- async storeContentIfLarge(content, metadata) {
127
- return await this.contentStorage.storeContentIfLarge(content, metadata);
446
+ async performCleanup() {
447
+ const startTime = Date.now();
448
+ const errors = [];
449
+ let cleanedUp = 0;
450
+ try {
451
+ const now = /* @__PURE__ */ new Date();
452
+ const toCleanup = [];
453
+ for (const [referenceId, storedContent] of this.contentStore.entries()) {
454
+ let shouldCleanup = false;
455
+ if (storedContent.expiresAt && storedContent.expiresAt < now) {
456
+ shouldCleanup = true;
457
+ storedContent.state = "expired";
458
+ }
459
+ const ageMs = now.getTime() - storedContent.metadata.createdAt.getTime();
460
+ const policy = this.getCleanupPolicy(storedContent.metadata.source);
461
+ if (ageMs > policy.maxAgeMs) {
462
+ shouldCleanup = true;
463
+ }
464
+ if (storedContent.state === "cleanup_pending") {
465
+ shouldCleanup = true;
466
+ }
467
+ if (shouldCleanup) {
468
+ toCleanup.push(referenceId);
469
+ }
470
+ }
471
+ toCleanup.sort((a, b) => {
472
+ const aContent = this.contentStore.get(a);
473
+ const bContent = this.contentStore.get(b);
474
+ const aPriority = this.getCleanupPolicy(aContent.metadata.source).priority;
475
+ const bPriority = this.getCleanupPolicy(bContent.metadata.source).priority;
476
+ return bPriority - aPriority;
477
+ });
478
+ for (const referenceId of toCleanup) {
479
+ try {
480
+ const success = await this.cleanupReference(referenceId);
481
+ if (success) {
482
+ cleanedUp++;
483
+ }
484
+ } catch (error) {
485
+ errors.push(`Failed to cleanup ${referenceId}: ${error instanceof Error ? error.message : "Unknown error"}`);
486
+ }
487
+ }
488
+ if (this.contentStore.size > this.referenceConfig.maxReferences) {
489
+ const sortedByAge = Array.from(this.contentStore.entries()).sort(([, a], [, b]) => a.metadata.lastAccessedAt.getTime() - b.metadata.lastAccessedAt.getTime());
490
+ const excessCount = this.contentStore.size - this.referenceConfig.maxReferences;
491
+ for (let i = 0; i < excessCount && i < sortedByAge.length; i++) {
492
+ const [referenceId] = sortedByAge[i];
493
+ try {
494
+ const success = await this.cleanupReference(referenceId);
495
+ if (success) {
496
+ cleanedUp++;
497
+ }
498
+ } catch (error) {
499
+ errors.push(`Failed to cleanup excess reference ${referenceId}: ${error instanceof Error ? error.message : "Unknown error"}`);
500
+ }
501
+ }
502
+ }
503
+ const duration = Date.now() - startTime;
504
+ this.recordPerformanceMetric("cleanup", duration);
505
+ return { cleanedUp, errors };
506
+ } catch (error) {
507
+ const duration = Date.now() - startTime;
508
+ this.recordPerformanceMetric("cleanup", duration);
509
+ const errorMessage = `Cleanup process failed: ${error instanceof Error ? error.message : "Unknown error"}`;
510
+ console.error("[ContentStorage]", errorMessage);
511
+ errors.push(errorMessage);
512
+ return { cleanedUp, errors };
513
+ }
128
514
  }
129
515
  /**
130
- * Cleanup and unregister
516
+ * Get reference configuration for debugging
131
517
  */
132
- async dispose() {
133
- if (this.isRegistered) {
134
- this.contentStorage.dispose();
135
- ContentStoreService.dispose();
136
- ContentResolverRegistry.unregister();
137
- this.isRegistered = false;
138
- this.logger.info("ContentStoreManager disposed and unregistered");
518
+ getReferenceConfig() {
519
+ return { ...this.referenceConfig };
520
+ }
521
+ async enforceReferenceStorageLimits() {
522
+ if (this.contentStore.size >= this.referenceConfig.maxReferences) {
523
+ await this.performCleanup();
524
+ }
525
+ if (this.referenceStats.totalStorageBytes >= this.referenceConfig.maxTotalStorageBytes) {
526
+ await this.performCleanup();
527
+ }
528
+ }
529
+ calculateExpirationTime(source) {
530
+ const policy = this.getCleanupPolicy(source);
531
+ return new Date(Date.now() + policy.maxAgeMs);
532
+ }
533
+ getCleanupPolicy(source) {
534
+ switch (source) {
535
+ case "mcp_tool":
536
+ return this.referenceConfig.cleanupPolicies.recent;
537
+ case "user_upload":
538
+ return this.referenceConfig.cleanupPolicies.userContent;
539
+ case "agent_generated":
540
+ return this.referenceConfig.cleanupPolicies.agentGenerated;
541
+ default:
542
+ return this.referenceConfig.cleanupPolicies.default;
139
543
  }
140
544
  }
545
+ detectContentType(content, mimeType) {
546
+ if (mimeType) {
547
+ if (mimeType === "text/html") return "html";
548
+ if (mimeType === "text/markdown") return "markdown";
549
+ if (mimeType === "application/json") return "json";
550
+ if (mimeType.startsWith("text/")) return "text";
551
+ return "binary";
552
+ }
553
+ const contentStr = content.toString("utf8", 0, Math.min(content.length, 1e3));
554
+ if (contentStr.startsWith("{") || contentStr.startsWith("[")) return "json";
555
+ if (contentStr.includes("<html>") || contentStr.includes("<!DOCTYPE")) return "html";
556
+ if (contentStr.includes("#") && contentStr.includes("\n")) return "markdown";
557
+ return "text";
558
+ }
559
+ createContentPreview(content, contentType) {
560
+ const maxLength = 200;
561
+ let preview = content.toString("utf8", 0, Math.min(content.length, maxLength * 2));
562
+ if (contentType === "html") {
563
+ preview = preview.replace(/<[^>]*>/g, "").replace(/\s+/g, " ").trim();
564
+ } else if (contentType === "json") {
565
+ try {
566
+ const parsed = JSON.parse(preview);
567
+ preview = JSON.stringify(parsed, null, 0);
568
+ } catch {
569
+ }
570
+ }
571
+ preview = preview.trim();
572
+ if (preview.length > maxLength) {
573
+ preview = preview.substring(0, maxLength) + "...";
574
+ }
575
+ return preview || "[Binary content]";
576
+ }
577
+ updateStatsAfterStore(sizeBytes) {
578
+ this.referenceStats.activeReferences++;
579
+ this.referenceStats.totalStorageBytes += sizeBytes;
580
+ this.updateReferenceStorageStats();
581
+ }
582
+ updateReferenceStorageStats() {
583
+ if (this.referenceStats.activeReferences > 0) {
584
+ this.referenceStats.averageContentSize = this.referenceStats.totalStorageBytes / this.referenceStats.activeReferences;
585
+ }
586
+ this.referenceStats.storageUtilization = this.referenceStats.totalStorageBytes / this.referenceConfig.maxTotalStorageBytes * 100;
587
+ let mostAccessedId;
588
+ let maxAccess = 0;
589
+ for (const [referenceId, storedContent] of this.contentStore.entries()) {
590
+ if (storedContent.metadata.accessCount > maxAccess) {
591
+ maxAccess = storedContent.metadata.accessCount;
592
+ mostAccessedId = referenceId;
593
+ }
594
+ }
595
+ if (mostAccessedId !== void 0) {
596
+ this.referenceStats.mostAccessedReferenceId = mostAccessedId;
597
+ } else {
598
+ delete this.referenceStats.mostAccessedReferenceId;
599
+ }
600
+ }
601
+ recordPerformanceMetric(type, timeMs) {
602
+ const metrics = this.referenceStats.performanceMetrics;
603
+ const maxRecords = 100;
604
+ switch (type) {
605
+ case "creation":
606
+ metrics.creationTimes.push(timeMs);
607
+ if (metrics.creationTimes.length > maxRecords) {
608
+ metrics.creationTimes.shift();
609
+ }
610
+ break;
611
+ case "resolution":
612
+ metrics.resolutionTimes.push(timeMs);
613
+ if (metrics.resolutionTimes.length > maxRecords) {
614
+ metrics.resolutionTimes.shift();
615
+ }
616
+ break;
617
+ case "cleanup":
618
+ metrics.cleanupTimes.push(timeMs);
619
+ if (metrics.cleanupTimes.length > maxRecords) {
620
+ metrics.cleanupTimes.shift();
621
+ }
622
+ break;
623
+ }
624
+ }
625
+ calculateAverage(times) {
626
+ if (times.length === 0) return 0;
627
+ return times.reduce((sum, time) => sum + time, 0) / times.length;
628
+ }
629
+ startReferenceCleanupTimer() {
630
+ this.cleanupTimer = setInterval(async () => {
631
+ try {
632
+ await this.performCleanup();
633
+ } catch (error) {
634
+ console.error("Error in scheduled reference cleanup:", error);
635
+ }
636
+ }, this.referenceConfig.cleanupIntervalMs);
637
+ }
141
638
  /**
142
- * Check if the manager is initialized
639
+ * Clean up resources (enhanced to include reference cleanup)
143
640
  */
144
- isInitialized() {
145
- return this.isRegistered;
641
+ async dispose() {
642
+ if (this.cleanupTimer) {
643
+ clearInterval(this.cleanupTimer);
644
+ delete this.cleanupTimer;
645
+ }
646
+ this.contentStore.clear();
647
+ this.clear();
146
648
  }
147
- }
649
+ };
650
+ _ContentStorage.DEFAULT_MAX_STORAGE = 1e3;
651
+ let ContentStorage = _ContentStorage;
148
652
  export {
149
- ContentStoreManager
653
+ ContentStorage
150
654
  };
151
655
  //# sourceMappingURL=index14.js.map