@robota-sdk/agent-plugin 3.0.0-beta.64

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/node/index.cjs +1 -0
  3. package/dist/node/index.d.ts +1724 -0
  4. package/dist/node/index.d.ts.map +1 -0
  5. package/dist/node/index.js +2 -0
  6. package/dist/node/index.js.map +1 -0
  7. package/package.json +48 -0
  8. package/src/conversation-history/__tests__/conversation-history-plugin.test.ts +221 -0
  9. package/src/conversation-history/__tests__/history-storages.test.ts +115 -0
  10. package/src/conversation-history/conversation-history-helpers.ts +120 -0
  11. package/src/conversation-history/conversation-history-plugin.ts +294 -0
  12. package/src/conversation-history/index.ts +11 -0
  13. package/src/conversation-history/storages/database-storage.ts +96 -0
  14. package/src/conversation-history/storages/file-storage.ts +95 -0
  15. package/src/conversation-history/storages/index.ts +3 -0
  16. package/src/conversation-history/storages/memory-storage.ts +44 -0
  17. package/src/conversation-history/types.ts +64 -0
  18. package/src/error-handling/__tests__/error-handling-plugin.test.ts +201 -0
  19. package/src/error-handling/context-adapter.ts +48 -0
  20. package/src/error-handling/error-handling-helpers.ts +53 -0
  21. package/src/error-handling/error-handling-plugin.ts +293 -0
  22. package/src/error-handling/index.ts +9 -0
  23. package/src/error-handling/types.ts +82 -0
  24. package/src/execution-analytics/__tests__/execution-analytics-plugin.test.ts +224 -0
  25. package/src/execution-analytics/analytics-aggregation.ts +88 -0
  26. package/src/execution-analytics/execution-analytics-helpers.ts +83 -0
  27. package/src/execution-analytics/execution-analytics-plugin.ts +315 -0
  28. package/src/execution-analytics/index.ts +9 -0
  29. package/src/execution-analytics/types.ts +97 -0
  30. package/src/index.ts +8 -0
  31. package/src/limits/__tests__/limits-plugin.test.ts +712 -0
  32. package/src/limits/index.ts +9 -0
  33. package/src/limits/limits-helpers.ts +185 -0
  34. package/src/limits/limits-plugin.ts +196 -0
  35. package/src/limits/types.ts +73 -0
  36. package/src/limits/validation.ts +81 -0
  37. package/src/logging/__tests__/formatters.test.ts +48 -0
  38. package/src/logging/__tests__/logging-plugin.test.ts +464 -0
  39. package/src/logging/__tests__/logging-storages.test.ts +95 -0
  40. package/src/logging/formatters.ts +28 -0
  41. package/src/logging/index.ts +15 -0
  42. package/src/logging/logging-helpers.ts +223 -0
  43. package/src/logging/logging-plugin.ts +288 -0
  44. package/src/logging/storages/console-storage.ts +44 -0
  45. package/src/logging/storages/file-storage.ts +44 -0
  46. package/src/logging/storages/index.ts +4 -0
  47. package/src/logging/storages/remote-storage.ts +78 -0
  48. package/src/logging/storages/silent-storage.ts +18 -0
  49. package/src/logging/types.ts +106 -0
  50. package/src/performance/__tests__/memory-storage.test.ts +86 -0
  51. package/src/performance/__tests__/performance-plugin.test.ts +208 -0
  52. package/src/performance/__tests__/system-metrics-collector.test.ts +33 -0
  53. package/src/performance/collectors/system-metrics-collector.ts +69 -0
  54. package/src/performance/index.ts +12 -0
  55. package/src/performance/performance-helpers.ts +86 -0
  56. package/src/performance/performance-plugin.ts +274 -0
  57. package/src/performance/storages/index.ts +1 -0
  58. package/src/performance/storages/memory-storage.ts +88 -0
  59. package/src/performance/types.ts +160 -0
  60. package/src/usage/__tests__/aggregate-usage-stats.test.ts +136 -0
  61. package/src/usage/__tests__/memory-storage.test.ts +83 -0
  62. package/src/usage/__tests__/silent-storage.test.ts +44 -0
  63. package/src/usage/__tests__/usage-plugin-helpers.test.ts +155 -0
  64. package/src/usage/__tests__/usage-plugin.test.ts +358 -0
  65. package/src/usage/aggregate-usage-stats.ts +142 -0
  66. package/src/usage/index.ts +14 -0
  67. package/src/usage/storages/file-storage.ts +115 -0
  68. package/src/usage/storages/index.ts +4 -0
  69. package/src/usage/storages/memory-storage.ts +61 -0
  70. package/src/usage/storages/remote-storage.ts +143 -0
  71. package/src/usage/storages/silent-storage.ts +38 -0
  72. package/src/usage/types.ts +132 -0
  73. package/src/usage/usage-plugin-helpers.ts +116 -0
  74. package/src/usage/usage-plugin.ts +296 -0
  75. package/src/webhook/__tests__/webhook-plugin.test.ts +560 -0
  76. package/src/webhook/http-client.ts +141 -0
  77. package/src/webhook/index.ts +9 -0
  78. package/src/webhook/transformer.ts +209 -0
  79. package/src/webhook/types.ts +201 -0
  80. package/src/webhook/webhook-helpers.ts +60 -0
  81. package/src/webhook/webhook-plugin.ts +298 -0
  82. package/src/webhook/webhook-queue.ts +148 -0
@@ -0,0 +1,294 @@
1
+ import {
2
+ AbstractPlugin,
3
+ PluginCategory,
4
+ PluginPriority,
5
+ type TUniversalMessage,
6
+ createLogger,
7
+ type ILogger,
8
+ PluginError,
9
+ type TTimerId,
10
+ startPeriodicTask,
11
+ stopPeriodicTask,
12
+ } from '@robota-sdk/agent-core';
13
+ import {
14
+ IConversationHistoryPluginOptions,
15
+ IConversationHistoryPluginStats,
16
+ IConversationHistoryEntry,
17
+ IHistoryStorage,
18
+ } from './types';
19
+ import {
20
+ validateConversationHistoryOptions,
21
+ createHistoryStorage,
22
+ loadConversationEntry,
23
+ savePendingConversations,
24
+ } from './conversation-history-helpers';
25
+
26
+ const DEFAULT_MAX_CONVERSATIONS = 100;
27
+ const DEFAULT_MAX_MESSAGES = 1000;
28
+ const DEFAULT_SAVE_INTERVAL_MS = 30000;
29
+
30
+ /**
31
+ * Persists conversation history using configurable storage backends.
32
+ *
33
+ * Supports memory, file, and database storage strategies. Messages are
34
+ * automatically trimmed to {@link IConversationHistoryPluginOptions.maxMessagesPerConversation | maxMessagesPerConversation}.
35
+ * When {@link IConversationHistoryPluginOptions.autoSave | autoSave} is
36
+ * disabled, changes are batched and flushed on a timer.
37
+ *
38
+ * @extends AbstractPlugin
39
+ * @see IHistoryStorage - storage backend contract
40
+ * @see IConversationHistoryPluginOptions - configuration options
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * const plugin = new ConversationHistoryPlugin({
45
+ * storage: 'memory',
46
+ * maxMessagesPerConversation: 500,
47
+ * });
48
+ * await plugin.startConversation('conv-1');
49
+ * await plugin.addMessage({ role: 'user', content: 'Hello' });
50
+ * ```
51
+ */
52
+ export class ConversationHistoryPlugin extends AbstractPlugin<
53
+ IConversationHistoryPluginOptions,
54
+ IConversationHistoryPluginStats
55
+ > {
56
+ name = 'ConversationHistoryPlugin';
57
+ version = '1.0.0';
58
+
59
+ private storage: IHistoryStorage;
60
+ private pluginOptions: Required<IConversationHistoryPluginOptions>;
61
+ private logger: ILogger;
62
+ private currentConversationId?: string;
63
+ private batchSaveTimer?: TTimerId;
64
+ private pendingSaves = new Set<string>();
65
+
66
+ constructor(options: IConversationHistoryPluginOptions) {
67
+ super();
68
+ this.logger = createLogger('ConversationHistoryPlugin');
69
+
70
+ // Set plugin classification
71
+ this.category = PluginCategory.STORAGE;
72
+ this.priority = PluginPriority.HIGH;
73
+
74
+ // Validate options
75
+ validateConversationHistoryOptions(options);
76
+
77
+ // Set defaults
78
+ this.pluginOptions = {
79
+ enabled: options.enabled ?? true,
80
+ storage: options.storage,
81
+ maxConversations: options.maxConversations ?? DEFAULT_MAX_CONVERSATIONS,
82
+ maxMessagesPerConversation: options.maxMessagesPerConversation ?? DEFAULT_MAX_MESSAGES,
83
+ filePath: options.filePath ?? './conversations.json',
84
+ connectionString: options.connectionString ?? '',
85
+ autoSave: options.autoSave ?? true,
86
+ saveInterval: options.saveInterval ?? DEFAULT_SAVE_INTERVAL_MS,
87
+ // Add plugin options defaults
88
+ category: options.category ?? PluginCategory.STORAGE,
89
+ priority: options.priority ?? PluginPriority.HIGH,
90
+ moduleEvents: options.moduleEvents ?? [],
91
+ subscribeToAllModuleEvents: options.subscribeToAllModuleEvents ?? false,
92
+ };
93
+
94
+ // Initialize storage
95
+ this.storage = createHistoryStorage(
96
+ this.pluginOptions.storage,
97
+ this.pluginOptions.maxConversations,
98
+ this.pluginOptions.filePath,
99
+ this.pluginOptions.connectionString,
100
+ );
101
+
102
+ // Setup batch saving if not auto-saving
103
+ if (!this.pluginOptions.autoSave) {
104
+ this.setupBatchSaving();
105
+ }
106
+
107
+ this.logger.info('ConversationHistoryPlugin initialized', {
108
+ storage: this.pluginOptions.storage,
109
+ maxConversations: this.pluginOptions.maxConversations,
110
+ autoSave: this.pluginOptions.autoSave,
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Creates a new conversation entry and persists it (or queues for batch save).
116
+ * @throws PluginError if the storage write fails
117
+ */
118
+ async startConversation(conversationId: string): Promise<void> {
119
+ try {
120
+ this.currentConversationId = conversationId;
121
+
122
+ const entry: IConversationHistoryEntry = {
123
+ conversationId,
124
+ messages: [],
125
+ startTime: new Date(),
126
+ lastUpdated: new Date(),
127
+ metadata: {},
128
+ };
129
+
130
+ // Always persist the initial entry so subsequent loads can find it.
131
+ // autoSave=false only means we track the id for deferred external flush via savePending.
132
+ await this.storage.save(conversationId, entry);
133
+ if (!this.pluginOptions.autoSave) {
134
+ this.pendingSaves.add(conversationId);
135
+ }
136
+
137
+ this.logger.debug('Started new conversation', { conversationId });
138
+ } catch (error) {
139
+ throw new PluginError('Failed to start conversation', this.name, {
140
+ conversationId,
141
+ error: error instanceof Error ? error.message : String(error),
142
+ });
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Appends a message to the active conversation, trimming to the maximum
148
+ * message limit if exceeded.
149
+ * @throws PluginError if no conversation is active or the storage write fails
150
+ */
151
+ async addMessage(message: TUniversalMessage): Promise<void> {
152
+ if (!this.currentConversationId) {
153
+ throw new PluginError('No active conversation', this.name);
154
+ }
155
+
156
+ try {
157
+ const entry = (await this.storage.load(this.currentConversationId)) || {
158
+ conversationId: this.currentConversationId,
159
+ messages: [],
160
+ startTime: new Date(),
161
+ lastUpdated: new Date(),
162
+ metadata: {},
163
+ };
164
+
165
+ // Add message and trim if necessary
166
+ entry.messages.push(message);
167
+ if (entry.messages.length > this.pluginOptions.maxMessagesPerConversation) {
168
+ entry.messages = entry.messages.slice(-this.pluginOptions.maxMessagesPerConversation);
169
+ }
170
+ entry.lastUpdated = new Date();
171
+
172
+ // Always persist the updated entry. autoSave=false tracks it as pending
173
+ // for deferred external flush via savePending.
174
+ await this.storage.save(this.currentConversationId, entry);
175
+ if (!this.pluginOptions.autoSave) {
176
+ this.pendingSaves.add(this.currentConversationId);
177
+ }
178
+
179
+ this.logger.debug('Added message to conversation', {
180
+ conversationId: this.currentConversationId,
181
+ messageRole: message.role,
182
+ messageLength: message.content?.length ?? 0,
183
+ });
184
+ } catch (error) {
185
+ throw new PluginError('Failed to add message to conversation', this.name, {
186
+ conversationId: this.currentConversationId,
187
+ error: error instanceof Error ? error.message : String(error),
188
+ });
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Load conversation history
194
+ */
195
+ async loadConversation(conversationId: string): Promise<IConversationHistoryEntry | undefined> {
196
+ return loadConversationEntry(this.storage, conversationId, this.name, this.logger);
197
+ }
198
+
199
+ /**
200
+ * Get conversation history as messages
201
+ */
202
+ async getHistory(conversationId: string): Promise<TUniversalMessage[]> {
203
+ const entry = await this.loadConversation(conversationId);
204
+ return entry?.messages ?? [];
205
+ }
206
+
207
+ /**
208
+ * List all conversation IDs
209
+ */
210
+ async listConversations(): Promise<string[]> {
211
+ try {
212
+ return await this.storage.list();
213
+ } catch (error) {
214
+ throw new PluginError('Failed to list conversations', this.name, {
215
+ error: error instanceof Error ? error.message : String(error),
216
+ });
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Delete a conversation
222
+ */
223
+ async deleteConversation(conversationId: string): Promise<boolean> {
224
+ try {
225
+ const deleted = await this.storage.delete(conversationId);
226
+ this.pendingSaves.delete(conversationId);
227
+ this.logger.debug('Deleted conversation', { conversationId, deleted });
228
+ return deleted;
229
+ } catch (error) {
230
+ throw new PluginError('Failed to delete conversation', this.name, {
231
+ conversationId,
232
+ error: error instanceof Error ? error.message : String(error),
233
+ });
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Clear all conversations
239
+ */
240
+ async clearAllConversations(): Promise<void> {
241
+ try {
242
+ await this.storage.clear();
243
+ this.pendingSaves.clear();
244
+ this.logger.info('Cleared all conversations');
245
+ } catch (error) {
246
+ throw new PluginError('Failed to clear conversations', this.name, {
247
+ error: error instanceof Error ? error.message : String(error),
248
+ });
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Persists all conversations queued since the last save (batch mode only).
254
+ * Individual save failures are logged but do not abort the remaining saves.
255
+ */
256
+ async savePending(): Promise<void> {
257
+ await savePendingConversations(this.storage, this.pendingSaves, this.name, this.logger);
258
+ }
259
+
260
+ /**
261
+ * Stops the batch-save timer and flushes any pending conversation saves.
262
+ */
263
+ async destroy(): Promise<void> {
264
+ try {
265
+ stopPeriodicTask(this.batchSaveTimer);
266
+ this.batchSaveTimer = undefined;
267
+
268
+ // Save any pending conversations
269
+ await this.savePending();
270
+
271
+ this.logger.info('ConversationHistoryPlugin destroyed');
272
+ } catch (error) {
273
+ this.logger.error('Error during plugin cleanup', {
274
+ error: error instanceof Error ? error.message : String(error),
275
+ });
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Setup batch saving timer
281
+ */
282
+ private setupBatchSaving(): void {
283
+ this.batchSaveTimer = startPeriodicTask(
284
+ this.logger,
285
+ {
286
+ name: 'ConversationHistoryPlugin.savePending',
287
+ intervalMs: this.pluginOptions.saveInterval,
288
+ },
289
+ async () => {
290
+ await this.savePending();
291
+ },
292
+ );
293
+ }
294
+ }
@@ -0,0 +1,11 @@
1
+ export { ConversationHistoryPlugin } from './conversation-history-plugin';
2
+ export { MemoryHistoryStorage } from './storages/memory-storage';
3
+ export { FileHistoryStorage } from './storages/file-storage';
4
+ export { DatabaseHistoryStorage } from './storages/database-storage';
5
+ export type {
6
+ THistoryStorageStrategy,
7
+ IConversationHistoryEntry,
8
+ IConversationHistoryPluginOptions,
9
+ IConversationHistoryPluginStats,
10
+ IHistoryStorage,
11
+ } from './types';
@@ -0,0 +1,96 @@
1
+ import type { IHistoryStorage, IConversationHistoryEntry } from '../types';
2
+ import { createLogger, type ILogger, StorageError } from '@robota-sdk/agent-core';
3
+
4
+ /**
5
+ * Database storage implementation
6
+ */
7
+ export class DatabaseHistoryStorage implements IHistoryStorage {
8
+ private connectionString: string;
9
+ private logger: ILogger;
10
+
11
+ constructor(connectionString: string) {
12
+ this.connectionString = connectionString;
13
+ this.logger = createLogger('DatabaseHistoryStorage');
14
+ }
15
+
16
+ async save(conversationId: string, _entry: IConversationHistoryEntry): Promise<void> {
17
+ try {
18
+ // Database operations would be implemented here
19
+ this.logger.warn('Database storage not fully implemented yet', {
20
+ conversationId,
21
+ connectionString: this.maskConnectionString(),
22
+ });
23
+ } catch (error) {
24
+ throw new StorageError('Failed to save conversation to database', {
25
+ conversationId,
26
+ error: error instanceof Error ? error.message : String(error),
27
+ });
28
+ }
29
+ }
30
+
31
+ async load(conversationId: string): Promise<IConversationHistoryEntry | undefined> {
32
+ try {
33
+ // Database operations would be implemented here
34
+ this.logger.warn('Database storage not fully implemented yet', {
35
+ conversationId,
36
+ connectionString: this.maskConnectionString(),
37
+ });
38
+ return undefined;
39
+ } catch (error) {
40
+ throw new StorageError('Failed to load conversation from database', {
41
+ conversationId,
42
+ error: error instanceof Error ? error.message : String(error),
43
+ });
44
+ }
45
+ }
46
+
47
+ async list(): Promise<string[]> {
48
+ try {
49
+ // Database operations would be implemented here
50
+ this.logger.warn('Database storage not fully implemented yet', {
51
+ connectionString: this.maskConnectionString(),
52
+ });
53
+ return [];
54
+ } catch (error) {
55
+ throw new StorageError('Failed to list conversations from database', {
56
+ error: error instanceof Error ? error.message : String(error),
57
+ });
58
+ }
59
+ }
60
+
61
+ async delete(conversationId: string): Promise<boolean> {
62
+ try {
63
+ // Database operations would be implemented here
64
+ this.logger.warn('Database storage not fully implemented yet', {
65
+ conversationId,
66
+ connectionString: this.maskConnectionString(),
67
+ });
68
+ return false;
69
+ } catch (error) {
70
+ throw new StorageError('Failed to delete conversation from database', {
71
+ conversationId,
72
+ error: error instanceof Error ? error.message : String(error),
73
+ });
74
+ }
75
+ }
76
+
77
+ async clear(): Promise<void> {
78
+ try {
79
+ // Database operations would be implemented here
80
+ this.logger.warn('Database storage not fully implemented yet', {
81
+ connectionString: this.maskConnectionString(),
82
+ });
83
+ } catch (error) {
84
+ throw new StorageError('Failed to clear conversations from database', {
85
+ error: error instanceof Error ? error.message : String(error),
86
+ });
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Mask sensitive information in connection string for logging
92
+ */
93
+ private maskConnectionString(): string {
94
+ return this.connectionString.replace(/(:\/\/[^:]+:)[^@]+(@)/, '$1***$2');
95
+ }
96
+ }
@@ -0,0 +1,95 @@
1
+ import type { IHistoryStorage, IConversationHistoryEntry } from '../types';
2
+ import { createLogger, type ILogger, StorageError } from '@robota-sdk/agent-core';
3
+
4
+ /**
5
+ * File storage implementation
6
+ */
7
+ export class FileHistoryStorage implements IHistoryStorage {
8
+ private filePath: string;
9
+ private logger: ILogger;
10
+
11
+ constructor(filePath: string) {
12
+ this.filePath = filePath;
13
+ this.logger = createLogger('FileHistoryStorage');
14
+ }
15
+
16
+ async save(conversationId: string, _entry: IConversationHistoryEntry): Promise<void> {
17
+ try {
18
+ // File operations would be implemented here
19
+ // This is a placeholder for actual file system operations
20
+ this.logger.warn('File storage not fully implemented yet', {
21
+ conversationId,
22
+ filePath: this.filePath,
23
+ });
24
+ } catch (error) {
25
+ throw new StorageError('Failed to save conversation to file', {
26
+ conversationId,
27
+ filePath: this.filePath,
28
+ error: error instanceof Error ? error.message : String(error),
29
+ });
30
+ }
31
+ }
32
+
33
+ async load(conversationId: string): Promise<IConversationHistoryEntry | undefined> {
34
+ try {
35
+ // File operations would be implemented here
36
+ this.logger.warn('File storage not fully implemented yet', {
37
+ conversationId,
38
+ filePath: this.filePath,
39
+ });
40
+ return undefined;
41
+ } catch (error) {
42
+ throw new StorageError('Failed to load conversation from file', {
43
+ conversationId,
44
+ filePath: this.filePath,
45
+ error: error instanceof Error ? error.message : String(error),
46
+ });
47
+ }
48
+ }
49
+
50
+ async list(): Promise<string[]> {
51
+ try {
52
+ // File operations would be implemented here
53
+ this.logger.warn('File storage not fully implemented yet', {
54
+ filePath: this.filePath,
55
+ });
56
+ return [];
57
+ } catch (error) {
58
+ throw new StorageError('Failed to list conversations from file', {
59
+ filePath: this.filePath,
60
+ error: error instanceof Error ? error.message : String(error),
61
+ });
62
+ }
63
+ }
64
+
65
+ async delete(conversationId: string): Promise<boolean> {
66
+ try {
67
+ // File operations would be implemented here
68
+ this.logger.warn('File storage not fully implemented yet', {
69
+ conversationId,
70
+ filePath: this.filePath,
71
+ });
72
+ return false;
73
+ } catch (error) {
74
+ throw new StorageError('Failed to delete conversation from file', {
75
+ conversationId,
76
+ filePath: this.filePath,
77
+ error: error instanceof Error ? error.message : String(error),
78
+ });
79
+ }
80
+ }
81
+
82
+ async clear(): Promise<void> {
83
+ try {
84
+ // File operations would be implemented here
85
+ this.logger.warn('File storage not fully implemented yet', {
86
+ filePath: this.filePath,
87
+ });
88
+ } catch (error) {
89
+ throw new StorageError('Failed to clear conversations from file', {
90
+ filePath: this.filePath,
91
+ error: error instanceof Error ? error.message : String(error),
92
+ });
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,3 @@
1
+ export { MemoryHistoryStorage } from './memory-storage';
2
+ export { FileHistoryStorage } from './file-storage';
3
+ export { DatabaseHistoryStorage } from './database-storage';
@@ -0,0 +1,44 @@
1
+ import type { IHistoryStorage, IConversationHistoryEntry } from '../types';
2
+
3
+ /**
4
+ * Memory storage implementation
5
+ */
6
+ export class MemoryHistoryStorage implements IHistoryStorage {
7
+ private conversations = new Map<string, IConversationHistoryEntry>();
8
+ private maxConversations: number;
9
+
10
+ constructor(maxConversations: number = 100) {
11
+ this.maxConversations = maxConversations;
12
+ }
13
+
14
+ async save(conversationId: string, entry: IConversationHistoryEntry): Promise<void> {
15
+ // Remove oldest conversation if limit exceeded
16
+ if (
17
+ this.conversations.size >= this.maxConversations &&
18
+ !this.conversations.has(conversationId)
19
+ ) {
20
+ const oldestId = this.conversations.keys().next().value;
21
+ if (oldestId) {
22
+ this.conversations.delete(oldestId);
23
+ }
24
+ }
25
+
26
+ this.conversations.set(conversationId, { ...entry });
27
+ }
28
+
29
+ async load(conversationId: string): Promise<IConversationHistoryEntry | undefined> {
30
+ return this.conversations.get(conversationId);
31
+ }
32
+
33
+ async list(): Promise<string[]> {
34
+ return Array.from(this.conversations.keys());
35
+ }
36
+
37
+ async delete(conversationId: string): Promise<boolean> {
38
+ return this.conversations.delete(conversationId);
39
+ }
40
+
41
+ async clear(): Promise<void> {
42
+ this.conversations.clear();
43
+ }
44
+ }
@@ -0,0 +1,64 @@
1
+ import type { TUniversalMessage, IPluginOptions, IPluginStats } from '@robota-sdk/agent-core';
2
+
3
+ /**
4
+ * Storage strategy for conversation history
5
+ */
6
+ export type THistoryStorageStrategy = 'memory' | 'file' | 'database';
7
+
8
+ /**
9
+ * Configuration options for conversation history plugin
10
+ */
11
+ export interface IConversationHistoryPluginOptions extends IPluginOptions {
12
+ /** Storage strategy to use */
13
+ storage: THistoryStorageStrategy;
14
+ /** Maximum number of conversations to store */
15
+ maxConversations?: number;
16
+ /** Maximum messages per conversation */
17
+ maxMessagesPerConversation?: number;
18
+ /** File path for file storage strategy */
19
+ filePath?: string;
20
+ /** Database connection string for database storage */
21
+ connectionString?: string;
22
+ /** Whether to auto-save after each message */
23
+ autoSave?: boolean;
24
+ /** Save interval in milliseconds for batch saving */
25
+ saveInterval?: number;
26
+ }
27
+
28
+ /**
29
+ * Conversation history entry
30
+ */
31
+ export interface IConversationHistoryEntry {
32
+ conversationId: string;
33
+ messages: TUniversalMessage[];
34
+ startTime: Date;
35
+ lastUpdated: Date;
36
+ metadata?: Record<string, string | number | boolean | Date>;
37
+ }
38
+
39
+ /**
40
+ * Storage interface for conversation history
41
+ */
42
+ export interface IHistoryStorage {
43
+ save(conversationId: string, entry: IConversationHistoryEntry): Promise<void>;
44
+ load(conversationId: string): Promise<IConversationHistoryEntry | undefined>;
45
+ list(): Promise<string[]>;
46
+ delete(conversationId: string): Promise<boolean>;
47
+ clear(): Promise<void>;
48
+ }
49
+
50
+ /**
51
+ * Conversation history plugin statistics
52
+ */
53
+ export interface IConversationHistoryPluginStats extends IPluginStats {
54
+ /** Total number of conversations stored */
55
+ totalConversations: number;
56
+ /** Total number of messages stored */
57
+ totalMessages: number;
58
+ /** Storage strategy in use */
59
+ storageStrategy: THistoryStorageStrategy;
60
+ /** Last save timestamp */
61
+ lastSaveTime?: Date;
62
+ /** Number of failed saves */
63
+ failedSaves: number;
64
+ }