@louloulinx/metagpt 0.1.3

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 (113) hide show
  1. package/.eslintrc.json +23 -0
  2. package/.prettierrc +7 -0
  3. package/LICENSE +21 -0
  4. package/README-CN.md +754 -0
  5. package/README.md +238 -0
  6. package/bun.lock +1023 -0
  7. package/doc/TutorialAssistant.md +114 -0
  8. package/doc/VercelLLMProvider.md +164 -0
  9. package/eslint.config.js +55 -0
  10. package/examples/data-interpreter-example.ts +173 -0
  11. package/examples/qwen-direct-example.ts +60 -0
  12. package/examples/qwen-example.ts +62 -0
  13. package/examples/tutorial-assistant-example.ts +97 -0
  14. package/jest.config.ts +22 -0
  15. package/output/tutorials/Go/350/257/255/350/250/200/347/274/226/347/250/213/346/225/231/347/250/213_2025-02-25T09-35-15-436Z.md +2208 -0
  16. package/output/tutorials/Rust/346/225/231/347/250/213_2025-02-25T08-27-27-632Z.md +1967 -0
  17. package/output/tutorials//345/246/202/344/275/225/344/275/277/347/224/250TypeScript/345/274/200/345/217/221Node.js/345/272/224/347/224/250_2025-02-25T08-14-39-605Z.md +1721 -0
  18. package/output/tutorials//346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/346/225/231/347/250/213_2025-02-25T10-45-03-605Z.md +902 -0
  19. package/output/tutorials//346/232/250/345/215/227/345/244/247/345/255/246/346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/345/244/215/350/257/225/350/265/204/346/226/231_2025-02-25T11-16-59-133Z.md +719 -0
  20. package/package.json +58 -0
  21. package/plan-cn.md +321 -0
  22. package/plan.md +154 -0
  23. package/src/actions/analyze-task.ts +65 -0
  24. package/src/actions/base-action.ts +103 -0
  25. package/src/actions/di/execute-nb-code.ts +247 -0
  26. package/src/actions/di/write-analysis-code.ts +234 -0
  27. package/src/actions/write-tutorial.ts +232 -0
  28. package/src/config/browser.ts +33 -0
  29. package/src/config/config.ts +345 -0
  30. package/src/config/embedding.ts +26 -0
  31. package/src/config/llm.ts +36 -0
  32. package/src/config/mermaid.ts +37 -0
  33. package/src/config/omniparse.ts +25 -0
  34. package/src/config/redis.ts +34 -0
  35. package/src/config/s3.ts +33 -0
  36. package/src/config/search.ts +30 -0
  37. package/src/config/workspace.ts +20 -0
  38. package/src/index.ts +40 -0
  39. package/src/management/team.ts +168 -0
  40. package/src/memory/longterm.ts +218 -0
  41. package/src/memory/manager.ts +160 -0
  42. package/src/memory/types.ts +100 -0
  43. package/src/memory/working.ts +154 -0
  44. package/src/monitoring/system.ts +413 -0
  45. package/src/monitoring/types.ts +230 -0
  46. package/src/plugin/manager.ts +79 -0
  47. package/src/plugin/types.ts +114 -0
  48. package/src/provider/vercel-llm.ts +314 -0
  49. package/src/rag/base-rag.ts +194 -0
  50. package/src/rag/document-qa.ts +102 -0
  51. package/src/roles/base-role.ts +155 -0
  52. package/src/roles/data-interpreter.ts +360 -0
  53. package/src/roles/engineer.ts +1 -0
  54. package/src/roles/tutorial-assistant.ts +217 -0
  55. package/src/skills/base-skill.ts +144 -0
  56. package/src/skills/code-review.ts +120 -0
  57. package/src/tools/base-tool.ts +155 -0
  58. package/src/tools/file-system.ts +204 -0
  59. package/src/tools/tool-recommend.d.ts +14 -0
  60. package/src/tools/tool-recommend.ts +31 -0
  61. package/src/types/action.ts +38 -0
  62. package/src/types/config.ts +129 -0
  63. package/src/types/document.ts +354 -0
  64. package/src/types/llm.ts +64 -0
  65. package/src/types/memory.ts +36 -0
  66. package/src/types/message.ts +193 -0
  67. package/src/types/rag.ts +86 -0
  68. package/src/types/role.ts +67 -0
  69. package/src/types/skill.ts +71 -0
  70. package/src/types/task.ts +32 -0
  71. package/src/types/team.ts +55 -0
  72. package/src/types/tool.ts +77 -0
  73. package/src/types/workflow.ts +133 -0
  74. package/src/utils/common.ts +73 -0
  75. package/src/utils/yaml.ts +67 -0
  76. package/src/websocket/browser-client.ts +187 -0
  77. package/src/websocket/client.ts +186 -0
  78. package/src/websocket/server.ts +169 -0
  79. package/src/websocket/types.ts +125 -0
  80. package/src/workflow/executor.ts +193 -0
  81. package/src/workflow/executors/action-executor.ts +72 -0
  82. package/src/workflow/executors/condition-executor.ts +118 -0
  83. package/src/workflow/executors/parallel-executor.ts +201 -0
  84. package/src/workflow/executors/role-executor.ts +76 -0
  85. package/src/workflow/executors/sequence-executor.ts +196 -0
  86. package/tests/actions.test.ts +105 -0
  87. package/tests/benchmark/performance.test.ts +147 -0
  88. package/tests/config/config.test.ts +115 -0
  89. package/tests/config.test.ts +106 -0
  90. package/tests/e2e/setup.ts +74 -0
  91. package/tests/e2e/workflow.test.ts +88 -0
  92. package/tests/llm.test.ts +84 -0
  93. package/tests/memory/memory.test.ts +164 -0
  94. package/tests/memory.test.ts +63 -0
  95. package/tests/monitoring/monitoring.test.ts +225 -0
  96. package/tests/plugin/plugin.test.ts +183 -0
  97. package/tests/provider/bailian-llm.test.ts +98 -0
  98. package/tests/rag.test.ts +162 -0
  99. package/tests/roles.test.ts +88 -0
  100. package/tests/skills.test.ts +166 -0
  101. package/tests/team.test.ts +143 -0
  102. package/tests/tools.test.ts +170 -0
  103. package/tests/types/document.test.ts +181 -0
  104. package/tests/types/message.test.ts +122 -0
  105. package/tests/utils/yaml.test.ts +110 -0
  106. package/tests/utils.test.ts +74 -0
  107. package/tests/websocket/browser-client.test.ts +1 -0
  108. package/tests/websocket/websocket.test.ts +42 -0
  109. package/tests/workflow/parallel-executor.test.ts +224 -0
  110. package/tests/workflow/sequence-executor.test.ts +207 -0
  111. package/tests/workflow.test.ts +290 -0
  112. package/tsconfig.json +27 -0
  113. package/typedoc.json +25 -0
@@ -0,0 +1,168 @@
1
+ import { z } from 'zod';
2
+ import { Environment } from '../environment/environment';
3
+ import { Context } from '../context/context';
4
+ import { Message } from '../types/message';
5
+ import { Role } from '../types/role';
6
+ import { TeamConfig, TeamConfigSchema, TeamState, TeamStateSchema } from '../types/team';
7
+ import { NoMoneyError } from '../utils/errors';
8
+ import { readJsonFile, writeJsonFile } from '../utils/file';
9
+ import { join } from 'path';
10
+
11
+ /**
12
+ * Team class for managing multiple roles (agents) and their interactions
13
+ */
14
+ export class Team {
15
+ private config: TeamConfig;
16
+ private state: TeamState;
17
+ private env: Environment;
18
+
19
+ /**
20
+ * Create a new team instance
21
+ * @param config Team configuration
22
+ */
23
+ constructor(config: TeamConfig) {
24
+ this.config = TeamConfigSchema.parse(config);
25
+ this.state = TeamStateSchema.parse({});
26
+
27
+ const context = config.context || new Context();
28
+ this.env = config.environment || new Environment({ context });
29
+
30
+ if (config.roles) {
31
+ this.hire(config.roles);
32
+ }
33
+
34
+ if (config.envDesc) {
35
+ this.env.setDescription(config.envDesc);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Hire roles to join the team
41
+ * @param roles List of roles to hire
42
+ */
43
+ public hire(roles: Role[]): void {
44
+ this.env.addRoles(roles);
45
+ }
46
+
47
+ /**
48
+ * Get the cost manager
49
+ */
50
+ public get costManager() {
51
+ return this.env.context.costManager;
52
+ }
53
+
54
+ /**
55
+ * Invest in the team
56
+ * @param amount Investment amount
57
+ */
58
+ public invest(amount: number): void {
59
+ this.config.investment = amount;
60
+ this.costManager.maxBudget = amount;
61
+ console.log(`Investment: $${amount}`);
62
+ }
63
+
64
+ /**
65
+ * Check if team has sufficient balance
66
+ * @throws {NoMoneyError} If insufficient funds
67
+ */
68
+ private checkBalance(): void {
69
+ if (this.costManager.totalCost >= this.costManager.maxBudget) {
70
+ throw new NoMoneyError(
71
+ this.costManager.totalCost,
72
+ `Insufficient funds: ${this.costManager.maxBudget}`
73
+ );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Run a project with given idea
79
+ * @param idea Project idea or requirement
80
+ * @param sendTo Target role (optional)
81
+ */
82
+ public runProject(idea: string, sendTo = ''): void {
83
+ this.config.idea = idea;
84
+
85
+ // Publish human requirement
86
+ this.env.publishMessage(
87
+ new Message({
88
+ role: 'Human',
89
+ content: idea,
90
+ causedBy: 'UserRequirement',
91
+ sendTo: sendTo || 'ALL'
92
+ })
93
+ );
94
+ }
95
+
96
+ /**
97
+ * Run the team for specified rounds
98
+ * @param rounds Number of rounds to run
99
+ * @param idea Optional project idea
100
+ * @param sendTo Optional target role
101
+ * @param autoArchive Whether to auto archive after completion
102
+ */
103
+ public async run(
104
+ rounds = 3,
105
+ idea = '',
106
+ sendTo = '',
107
+ autoArchive = true
108
+ ): Promise<Message[]> {
109
+ if (idea) {
110
+ this.runProject(idea, sendTo);
111
+ }
112
+
113
+ while (rounds > 0) {
114
+ if (this.env.isIdle) {
115
+ console.debug('All roles are idle.');
116
+ break;
117
+ }
118
+
119
+ rounds--;
120
+ this.checkBalance();
121
+ await this.env.run();
122
+
123
+ console.debug(`Max ${rounds} rounds left.`);
124
+ }
125
+
126
+ if (autoArchive) {
127
+ await this.env.archive();
128
+ }
129
+
130
+ return this.env.history;
131
+ }
132
+
133
+ /**
134
+ * Serialize team state to storage
135
+ * @param storagePath Storage path
136
+ */
137
+ public serialize(storagePath: string): void {
138
+ const teamPath = join(storagePath, 'team');
139
+ const teamInfoPath = join(teamPath, 'team.json');
140
+
141
+ const data = {
142
+ config: this.config,
143
+ state: this.state,
144
+ context: this.env.context.serialize()
145
+ };
146
+
147
+ writeJsonFile(teamInfoPath, data);
148
+ }
149
+
150
+ /**
151
+ * Deserialize team state from storage
152
+ * @param storagePath Storage path
153
+ * @param context Optional context
154
+ */
155
+ public static deserialize(storagePath: string, context?: Context): Team {
156
+ const teamPath = join(storagePath, 'team');
157
+ const teamInfoPath = join(teamPath, 'team.json');
158
+
159
+ const data = readJsonFile(teamInfoPath);
160
+ const ctx = context || new Context();
161
+ ctx.deserialize(data.context);
162
+
163
+ return new Team({
164
+ ...data.config,
165
+ context: ctx
166
+ });
167
+ }
168
+ }
@@ -0,0 +1,218 @@
1
+ import type { LongTermMemory, WorkingMemory } from './types';
2
+ import type { MemoryEntrySchema, MemoryQueryOptions } from './types';
3
+ import type { z } from 'zod';
4
+ import { v4 as uuidv4 } from 'uuid';
5
+
6
+ /**
7
+ * Long-term memory implementation with persistence and consolidation
8
+ */
9
+ export class LongTermMemoryImpl implements LongTermMemory {
10
+ private memories: Map<string, z.infer<typeof MemoryEntrySchema>> = new Map();
11
+
12
+ /**
13
+ * Add a new memory
14
+ */
15
+ public async add(
16
+ content: string,
17
+ type: string,
18
+ metadata: Record<string, any> = {}
19
+ ): Promise<z.infer<typeof MemoryEntrySchema>> {
20
+ const memory = {
21
+ id: uuidv4(),
22
+ content,
23
+ type,
24
+ timestamp: Date.now(),
25
+ metadata,
26
+ importance: metadata.importance ?? 0.5,
27
+ embedding: metadata.embedding ?? [],
28
+ };
29
+
30
+ this.memories.set(memory.id, memory);
31
+ return memory;
32
+ }
33
+
34
+ /**
35
+ * Get a memory by ID
36
+ */
37
+ public async get(id: string): Promise<z.infer<typeof MemoryEntrySchema> | null> {
38
+ return this.memories.get(id) || null;
39
+ }
40
+
41
+ /**
42
+ * Search memories by query options
43
+ */
44
+ public async search(options: MemoryQueryOptions): Promise<z.infer<typeof MemoryEntrySchema>[]> {
45
+ let results = Array.from(this.memories.values());
46
+
47
+ // Apply filters
48
+ if (options.type) {
49
+ results = results.filter(m => m.type === options.type);
50
+ }
51
+
52
+ if (options.startTime) {
53
+ results = results.filter(m => m.timestamp >= options.startTime!);
54
+ }
55
+
56
+ if (options.endTime) {
57
+ results = results.filter(m => m.timestamp <= options.endTime!);
58
+ }
59
+
60
+ if (options.minImportance) {
61
+ results = results.filter(m => m.importance >= options.minImportance!);
62
+ }
63
+
64
+ if (options.metadata) {
65
+ results = results.filter(m => {
66
+ return Object.entries(options.metadata!).every(([key, value]) =>
67
+ m.metadata[key] === value
68
+ );
69
+ });
70
+ }
71
+
72
+ if (options.content) {
73
+ const searchContent = options.content.toLowerCase();
74
+ results = results.filter(m =>
75
+ m.content.toLowerCase().includes(searchContent) ||
76
+ searchContent.includes(m.content.toLowerCase())
77
+ );
78
+ }
79
+
80
+ // Sort by importance and timestamp
81
+ results.sort((a, b) => {
82
+ const importanceDiff = b.importance - a.importance;
83
+ return importanceDiff !== 0 ? importanceDiff : b.timestamp - a.timestamp;
84
+ });
85
+
86
+ // Apply limit
87
+ if (options.limit) {
88
+ results = results.slice(0, options.limit);
89
+ }
90
+
91
+ return results;
92
+ }
93
+
94
+ /**
95
+ * Update a memory
96
+ */
97
+ public async update(
98
+ id: string,
99
+ updates: Partial<z.infer<typeof MemoryEntrySchema>>
100
+ ): Promise<void> {
101
+ const memory = this.memories.get(id);
102
+ if (!memory) {
103
+ throw new Error(`Memory ${id} not found`);
104
+ }
105
+
106
+ Object.assign(memory, updates);
107
+ this.memories.set(id, memory);
108
+ }
109
+
110
+ /**
111
+ * Delete a memory
112
+ */
113
+ public async delete(id: string): Promise<void> {
114
+ this.memories.delete(id);
115
+ }
116
+
117
+ /**
118
+ * Clear all memories
119
+ */
120
+ public async clear(): Promise<void> {
121
+ this.memories.clear();
122
+ }
123
+
124
+ /**
125
+ * Consolidate memories from working memory
126
+ * This process involves:
127
+ * 1. Evaluating importance of working memories
128
+ * 2. Filtering out low importance memories
129
+ * 3. Generating embeddings for semantic search
130
+ * 4. Storing consolidated memories
131
+ */
132
+ public async consolidate(workingMemory: WorkingMemory): Promise<void> {
133
+ // Get all memories from working memory
134
+ const memories = await workingMemory.search({});
135
+
136
+ for (const memory of memories) {
137
+ // Skip if already consolidated
138
+ if (this.memories.has(memory.id)) {
139
+ continue;
140
+ }
141
+
142
+ // Check for similar existing memories
143
+ const similarMemories = await this.search({
144
+ content: memory.content,
145
+ limit: 1,
146
+ });
147
+
148
+ // If a very similar memory exists, update its importance instead of creating new
149
+ if (similarMemories.length > 0 &&
150
+ (similarMemories[0].content === memory.content ||
151
+ similarMemories[0].content.includes(memory.content) ||
152
+ memory.content.includes(similarMemories[0].content))) {
153
+ const existingMemory = similarMemories[0];
154
+ await this.update(existingMemory.id, {
155
+ importance: Math.max(existingMemory.importance, memory.importance),
156
+ metadata: {
157
+ ...existingMemory.metadata,
158
+ lastReinforced: Date.now(),
159
+ },
160
+ });
161
+ continue;
162
+ }
163
+
164
+ // Evaluate importance based on:
165
+ // - Explicit importance score
166
+ // - Age of memory
167
+ // - Number of related memories
168
+ const age = Date.now() - memory.timestamp;
169
+ const relatedMemories = await this.search({
170
+ content: memory.content,
171
+ limit: 5,
172
+ });
173
+
174
+ const importance = Math.min(
175
+ 1,
176
+ memory.importance * 0.7 + // Base importance has higher weight
177
+ (relatedMemories.length * 0.1) - // Related memories boost importance
178
+ (age / (24 * 60 * 60 * 1000) * 0.2) // Age reduces importance more significantly
179
+ );
180
+
181
+ // Add new memory with updated importance
182
+ await this.add(memory.content, memory.type, {
183
+ ...memory.metadata,
184
+ importance,
185
+ originalId: memory.id,
186
+ consolidatedAt: Date.now(),
187
+ });
188
+ }
189
+
190
+ // Clear consolidated memories from working memory
191
+ await workingMemory.clear();
192
+ }
193
+
194
+ /**
195
+ * Forget old or unimportant memories
196
+ */
197
+ public async forget(options: MemoryQueryOptions): Promise<void> {
198
+ const memories = Array.from(this.memories.values());
199
+
200
+ // Find memories to forget based on time and importance
201
+ const toForget = memories.filter(memory => {
202
+ // Check if memory is old enough using metadata timestamp if available
203
+ const timestamp = memory.metadata.timestamp ?? memory.timestamp;
204
+ const isOld = options.endTime ? timestamp <= options.endTime : false;
205
+
206
+ // Check if memory is not important enough
207
+ const isUnimportant = options.minImportance ? memory.importance < options.minImportance : false;
208
+
209
+ // Only forget memories that are both old and unimportant
210
+ return isOld && isUnimportant;
211
+ });
212
+
213
+ // Delete forgotten memories
214
+ for (const memory of toForget) {
215
+ await this.delete(memory.id);
216
+ }
217
+ }
218
+ }
@@ -0,0 +1,160 @@
1
+ import type { MemoryManager } from './types';
2
+ import type { Message } from '../types/message';
3
+ import type { z } from 'zod';
4
+ import type { MemoryEntrySchema } from './types';
5
+ import { WorkingMemoryImpl } from './working';
6
+ import { LongTermMemoryImpl } from './longterm';
7
+
8
+ /**
9
+ * Memory manager implementation for coordinating working and long-term memory
10
+ */
11
+ export class MemoryManagerImpl implements MemoryManager {
12
+ public readonly working: WorkingMemoryImpl;
13
+ public readonly longTerm: LongTermMemoryImpl;
14
+
15
+ constructor() {
16
+ this.working = new WorkingMemoryImpl();
17
+ this.longTerm = new LongTermMemoryImpl();
18
+ }
19
+
20
+ /**
21
+ * Initialize memory systems
22
+ */
23
+ public async init(): Promise<void> {
24
+ // Initialize working memory
25
+ await this.working.clear();
26
+
27
+ // Initialize long-term memory
28
+ await this.longTerm.clear();
29
+ }
30
+
31
+ /**
32
+ * Process a message through memory systems
33
+ * This involves:
34
+ * 1. Storing the message in working memory
35
+ * 2. Updating importance based on context
36
+ * 3. Triggering consolidation if needed
37
+ */
38
+ public async processMessage(message: Message): Promise<void> {
39
+ // Store message in working memory
40
+ const memory = await this.working.add(message.content, 'message', {
41
+ role: message.role,
42
+ causedBy: message.causedBy,
43
+ sentFrom: message.sentFrom,
44
+ sendTo: Array.from(message.sendTo),
45
+ instructContent: message.instructContent,
46
+ timestamp: Date.now(),
47
+ });
48
+
49
+ // Update importance based on:
50
+ // - Message role (system > assistant > user)
51
+ // - Presence of instruction content
52
+ // - Number of recipients
53
+ let importance = 0.5;
54
+
55
+ if (message.role === 'system') {
56
+ importance += 0.3;
57
+ } else if (message.role === 'assistant') {
58
+ importance += 0.2;
59
+ }
60
+
61
+ if (message.instructContent) {
62
+ importance += 0.1;
63
+ }
64
+
65
+ if (message.sendTo.size > 1) {
66
+ importance += 0.1;
67
+ }
68
+
69
+ await this.working.update(memory.id, { importance });
70
+
71
+ // Get working memory size
72
+ const workingMemories = await this.working.search({});
73
+
74
+ // Trigger consolidation if working memory is too large
75
+ if (workingMemories.length > 100) {
76
+ await this.longTerm.consolidate(this.working);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Retrieve relevant memories for context
82
+ */
83
+ public async getContext(message: Message): Promise<z.infer<typeof MemoryEntrySchema>[]> {
84
+ // Get recent memories from working memory (last 1 hour)
85
+ const oneHourAgo = Date.now() - 60 * 60 * 1000;
86
+ const workingMemories = await this.working.search({
87
+ startTime: oneHourAgo,
88
+ limit: 10,
89
+ });
90
+
91
+ // Get relevant memories from long-term memory using content search
92
+ const searchTerms = message.content.toLowerCase().split(/\s+/);
93
+ const longTermMemories = await this.longTerm.search({
94
+ content: message.content,
95
+ minImportance: 0.2,
96
+ limit: 20,
97
+ });
98
+
99
+ // Calculate relevance scores for all memories
100
+ const scoredMemories = [...workingMemories, ...longTermMemories].map(memory => {
101
+ // Time decay factor (exponential decay over 24 hours)
102
+ const timeDecay = Math.exp(-(Date.now() - memory.timestamp) / (24 * 60 * 60 * 1000));
103
+
104
+ // Content similarity (word overlap)
105
+ const memoryWords = memory.content.toLowerCase().split(/\s+/);
106
+ const overlap = searchTerms.filter(term =>
107
+ memoryWords.some(word => word.includes(term) || term.includes(word))
108
+ ).length;
109
+ const contentSimilarity = overlap / Math.max(searchTerms.length, memoryWords.length);
110
+
111
+ // Combine scores with weights
112
+ const score = (timeDecay * 0.2) + // Recency
113
+ (memory.importance * 0.3) + // Importance
114
+ (contentSimilarity * 0.5); // Content matching (higher weight)
115
+
116
+ return { memory, score };
117
+ });
118
+
119
+ // Sort by score and return top memories
120
+ return scoredMemories
121
+ .sort((a, b) => b.score - a.score)
122
+ .slice(0, 5)
123
+ .map(item => item.memory);
124
+ }
125
+
126
+ /**
127
+ * Calculate cosine similarity between two vectors
128
+ */
129
+ private calculateCosineSimilarity(a: number[], b: number[]): number {
130
+ if (a.length !== b.length) return 0;
131
+
132
+ const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
133
+ const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
134
+ const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
135
+
136
+ return magnitudeA && magnitudeB ? dotProduct / (magnitudeA * magnitudeB) : 0;
137
+ }
138
+
139
+ /**
140
+ * Cleanup memory systems
141
+ * This involves:
142
+ * 1. Consolidating remaining working memories
143
+ * 2. Forgetting old and unimportant memories
144
+ * 3. Clearing working memory
145
+ */
146
+ public async cleanup(): Promise<void> {
147
+ // Consolidate remaining working memories
148
+ await this.longTerm.consolidate(this.working);
149
+
150
+ // Forget old memories
151
+ const oneMonthAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
152
+ await this.longTerm.forget({
153
+ endTime: oneMonthAgo,
154
+ minImportance: 0.8, // Keep very important old memories
155
+ });
156
+
157
+ // Clear working memory
158
+ await this.working.clear();
159
+ }
160
+ }
@@ -0,0 +1,100 @@
1
+ import { z } from 'zod';
2
+ import type { Message } from '../types/message';
3
+
4
+ /**
5
+ * Memory entry schema for storing individual memories
6
+ */
7
+ export const MemoryEntrySchema = z.object({
8
+ /** Unique identifier for the memory */
9
+ id: z.string().uuid(),
10
+ /** Content of the memory */
11
+ content: z.string(),
12
+ /** Type of memory (e.g., conversation, fact, experience) */
13
+ type: z.string(),
14
+ /** Creation timestamp */
15
+ timestamp: z.number().default(() => Date.now()),
16
+ /** Associated metadata */
17
+ metadata: z.record(z.any()).default({}),
18
+ /** Importance score (0-1) */
19
+ importance: z.number().min(0).max(1).default(0.5),
20
+ /** Vector embedding for similarity search */
21
+ embedding: z.array(z.number()).optional(),
22
+ });
23
+
24
+ /**
25
+ * Memory query options
26
+ */
27
+ export interface MemoryQueryOptions {
28
+ /** Content to search for */
29
+ content?: string;
30
+ /** Type of memories to search */
31
+ type?: string;
32
+ /** Time range start */
33
+ startTime?: number;
34
+ /** Time range end */
35
+ endTime?: number;
36
+ /** Minimum importance score */
37
+ minImportance?: number;
38
+ /** Maximum number of results */
39
+ limit?: number;
40
+ /** Metadata filters */
41
+ metadata?: Record<string, any>;
42
+ }
43
+
44
+ /**
45
+ * Memory interface for storing and retrieving memories
46
+ */
47
+ export interface Memory {
48
+ /** Add a new memory */
49
+ add(content: string, type: string, metadata?: Record<string, any>): Promise<z.infer<typeof MemoryEntrySchema>>;
50
+ /** Get a memory by ID */
51
+ get(id: string): Promise<z.infer<typeof MemoryEntrySchema> | null>;
52
+ /** Search memories by query options */
53
+ search(options: MemoryQueryOptions): Promise<z.infer<typeof MemoryEntrySchema>[]>;
54
+ /** Update a memory */
55
+ update(id: string, updates: Partial<z.infer<typeof MemoryEntrySchema>>): Promise<void>;
56
+ /** Delete a memory */
57
+ delete(id: string): Promise<void>;
58
+ /** Clear all memories */
59
+ clear(): Promise<void>;
60
+ }
61
+
62
+ /**
63
+ * Working memory interface for temporary storage
64
+ */
65
+ export interface WorkingMemory extends Memory {
66
+ /** Get current focus of attention */
67
+ getFocus(): Promise<z.infer<typeof MemoryEntrySchema> | null>;
68
+ /** Set focus of attention */
69
+ setFocus(id: string): Promise<void>;
70
+ /** Clear focus of attention */
71
+ clearFocus(): Promise<void>;
72
+ }
73
+
74
+ /**
75
+ * Long-term memory interface for persistent storage
76
+ */
77
+ export interface LongTermMemory extends Memory {
78
+ /** Consolidate memories from working memory */
79
+ consolidate(workingMemory: WorkingMemory): Promise<void>;
80
+ /** Forget old or unimportant memories */
81
+ forget(options: MemoryQueryOptions): Promise<void>;
82
+ }
83
+
84
+ /**
85
+ * Memory manager interface for coordinating different memory types
86
+ */
87
+ export interface MemoryManager {
88
+ /** Working memory instance */
89
+ working: WorkingMemory;
90
+ /** Long-term memory instance */
91
+ longTerm: LongTermMemory;
92
+ /** Initialize memory systems */
93
+ init(): Promise<void>;
94
+ /** Process a message through memory */
95
+ processMessage(message: Message): Promise<void>;
96
+ /** Retrieve relevant memories for context */
97
+ getContext(message: Message): Promise<z.infer<typeof MemoryEntrySchema>[]>;
98
+ /** Cleanup memory systems */
99
+ cleanup(): Promise<void>;
100
+ }