@yun-zero/claw-memory 0.1.0

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 (131) hide show
  1. package/.claude/settings.local.json +68 -0
  2. package/README.md +323 -0
  3. package/dist/config/llm.d.ts +13 -0
  4. package/dist/config/llm.d.ts.map +1 -0
  5. package/dist/config/llm.js +96 -0
  6. package/dist/config/llm.js.map +1 -0
  7. package/dist/config/plugin.d.ts +15 -0
  8. package/dist/config/plugin.d.ts.map +1 -0
  9. package/dist/config/plugin.js +32 -0
  10. package/dist/config/plugin.js.map +1 -0
  11. package/dist/db/entityRepository.d.ts +21 -0
  12. package/dist/db/entityRepository.d.ts.map +1 -0
  13. package/dist/db/entityRepository.js +55 -0
  14. package/dist/db/entityRepository.js.map +1 -0
  15. package/dist/db/repository.d.ts +22 -0
  16. package/dist/db/repository.d.ts.map +1 -0
  17. package/dist/db/repository.js +77 -0
  18. package/dist/db/repository.js.map +1 -0
  19. package/dist/db/schema.d.ts +5 -0
  20. package/dist/db/schema.d.ts.map +1 -0
  21. package/dist/db/schema.js +112 -0
  22. package/dist/db/schema.js.map +1 -0
  23. package/dist/db/todoRepository.d.ts +26 -0
  24. package/dist/db/todoRepository.d.ts.map +1 -0
  25. package/dist/db/todoRepository.js +54 -0
  26. package/dist/db/todoRepository.js.map +1 -0
  27. package/dist/hooks/bootstrap.d.ts +3 -0
  28. package/dist/hooks/bootstrap.d.ts.map +1 -0
  29. package/dist/hooks/bootstrap.js +28 -0
  30. package/dist/hooks/bootstrap.js.map +1 -0
  31. package/dist/hooks/message.d.ts +18 -0
  32. package/dist/hooks/message.d.ts.map +1 -0
  33. package/dist/hooks/message.js +52 -0
  34. package/dist/hooks/message.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +46 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/mcp/tools.d.ts +26 -0
  40. package/dist/mcp/tools.d.ts.map +1 -0
  41. package/dist/mcp/tools.js +360 -0
  42. package/dist/mcp/tools.js.map +1 -0
  43. package/dist/plugin.d.ts +18 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +62 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/services/entityGraphService.d.ts +87 -0
  48. package/dist/services/entityGraphService.d.ts.map +1 -0
  49. package/dist/services/entityGraphService.js +271 -0
  50. package/dist/services/entityGraphService.js.map +1 -0
  51. package/dist/services/memory.d.ts +26 -0
  52. package/dist/services/memory.d.ts.map +1 -0
  53. package/dist/services/memory.js +281 -0
  54. package/dist/services/memory.js.map +1 -0
  55. package/dist/services/memoryIndex.d.ts +34 -0
  56. package/dist/services/memoryIndex.d.ts.map +1 -0
  57. package/dist/services/memoryIndex.js +100 -0
  58. package/dist/services/memoryIndex.js.map +1 -0
  59. package/dist/services/metadataExtractor.d.ts +16 -0
  60. package/dist/services/metadataExtractor.d.ts.map +1 -0
  61. package/dist/services/metadataExtractor.js +75 -0
  62. package/dist/services/metadataExtractor.js.map +1 -0
  63. package/dist/services/retrieval.d.ts +24 -0
  64. package/dist/services/retrieval.d.ts.map +1 -0
  65. package/dist/services/retrieval.js +40 -0
  66. package/dist/services/retrieval.js.map +1 -0
  67. package/dist/services/scheduler.d.ts +122 -0
  68. package/dist/services/scheduler.d.ts.map +1 -0
  69. package/dist/services/scheduler.js +434 -0
  70. package/dist/services/scheduler.js.map +1 -0
  71. package/dist/services/summarizer.d.ts +43 -0
  72. package/dist/services/summarizer.d.ts.map +1 -0
  73. package/dist/services/summarizer.js +252 -0
  74. package/dist/services/summarizer.js.map +1 -0
  75. package/dist/services/tagService.d.ts +64 -0
  76. package/dist/services/tagService.d.ts.map +1 -0
  77. package/dist/services/tagService.js +281 -0
  78. package/dist/services/tagService.js.map +1 -0
  79. package/dist/tools/memory.d.ts +3 -0
  80. package/dist/tools/memory.d.ts.map +1 -0
  81. package/dist/tools/memory.js +114 -0
  82. package/dist/tools/memory.js.map +1 -0
  83. package/dist/types.d.ts +128 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +6 -0
  86. package/dist/types.js.map +1 -0
  87. package/docs/plans/2026-03-02-claw-memory-design.md +445 -0
  88. package/docs/plans/2026-03-02-incremental-summary-design.md +157 -0
  89. package/docs/plans/2026-03-02-incremental-summary-implementation.md +468 -0
  90. package/docs/plans/2026-03-02-memory-index-design.md +163 -0
  91. package/docs/plans/2026-03-02-memory-index-implementation.md +836 -0
  92. package/docs/plans/2026-03-02-mvp-implementation.md +1703 -0
  93. package/docs/plans/2026-03-02-testing-implementation.md +395 -0
  94. package/docs/plans/2026-03-02-testing-plan.md +93 -0
  95. package/docs/plans/2026-03-03-claw-memory-openclaw-plugin-design.md +285 -0
  96. package/docs/plans/2026-03-03-claw-memory-plugin-implementation.md +642 -0
  97. package/docs/plans/2026-03-03-entity-graph-design.md +121 -0
  98. package/docs/plans/2026-03-03-entity-graph-implementation.md +687 -0
  99. package/docs/plans/2026-03-03-llm-generic-config-design.md +43 -0
  100. package/docs/plans/2026-03-03-llm-generic-config-implementation.md +186 -0
  101. package/docs/plans/2026-03-03-memory-e2e-stress-test-design.md +110 -0
  102. package/docs/plans/2026-03-03-memory-e2e-stress-test-implementation.md +464 -0
  103. package/docs/plans/2026-03-03-minimax-llm-fix.md +156 -0
  104. package/docs/plans/2026-03-03-scheduler-design.md +165 -0
  105. package/docs/plans/2026-03-03-scheduler-implementation.md +777 -0
  106. package/docs/plans/2026-03-03-tags-visualization-design.md +73 -0
  107. package/docs/plans/2026-03-03-tags-visualization-implementation.md +539 -0
  108. package/openclaw.plugin.json +11 -0
  109. package/package.json +41 -0
  110. package/src/config/llm.ts +129 -0
  111. package/src/config/plugin.ts +47 -0
  112. package/src/db/entityRepository.ts +80 -0
  113. package/src/db/repository.ts +106 -0
  114. package/src/db/schema.ts +121 -0
  115. package/src/db/todoRepository.ts +76 -0
  116. package/src/hooks/bootstrap.ts +36 -0
  117. package/src/hooks/message.ts +84 -0
  118. package/src/index.ts +50 -0
  119. package/src/plugin.ts +85 -0
  120. package/src/services/entityGraphService.ts +367 -0
  121. package/src/services/memory.ts +338 -0
  122. package/src/services/memoryIndex.ts +140 -0
  123. package/src/services/metadataExtractor.ts +89 -0
  124. package/src/services/retrieval.ts +71 -0
  125. package/src/services/scheduler.ts +529 -0
  126. package/src/services/summarizer.ts +318 -0
  127. package/src/services/tagService.ts +335 -0
  128. package/src/tools/memory.ts +137 -0
  129. package/src/types.ts +139 -0
  130. package/tsconfig.json +20 -0
  131. package/vitest.config.ts +16 -0
@@ -0,0 +1,137 @@
1
+ import type { Database } from 'better-sqlite3';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import * as path from 'path';
4
+ import * as fs from 'fs';
5
+ import { homedir } from 'os';
6
+
7
+ export function registerMemoryTools(
8
+ tools: any,
9
+ db: Database,
10
+ dataDir: string
11
+ ) {
12
+ // 解析 dataDir 中的 ~
13
+ const resolvedDataDir = dataDir.replace(/^~/, homedir());
14
+
15
+ // memory_save tool
16
+ tools.register({
17
+ name: 'memory_save',
18
+ description: 'Save conversation to memory with metadata',
19
+ schema: {
20
+ type: 'object',
21
+ properties: {
22
+ content: { type: 'string', description: 'Conversation content' },
23
+ metadata: {
24
+ type: 'object',
25
+ properties: {
26
+ tags: { type: 'array', items: { type: 'string' } },
27
+ keywords: { type: 'array', items: { type: 'string' } },
28
+ importance: { type: 'number', minimum: 0, maximum: 1 }
29
+ }
30
+ }
31
+ },
32
+ required: ['content']
33
+ },
34
+ handler: async (params: any) => {
35
+ const { content, metadata = {} } = params;
36
+ const memoryId = uuidv4();
37
+
38
+ const memoriesDir = path.join(resolvedDataDir, 'memories');
39
+ if (!fs.existsSync(memoriesDir)) {
40
+ fs.mkdirSync(memoriesDir, { recursive: true });
41
+ }
42
+
43
+ const contentPath = path.join(memoriesDir, `${memoryId}.md`);
44
+ fs.writeFileSync(contentPath, content, 'utf-8');
45
+
46
+ db.prepare(`
47
+ INSERT INTO memories (id, content_path, summary, importance, created_at)
48
+ VALUES (?, ?, ?, ?, datetime('now'))
49
+ `).run(
50
+ memoryId,
51
+ contentPath,
52
+ metadata.summary || content.substring(0, 200),
53
+ metadata.importance || 0.5
54
+ );
55
+
56
+ return { success: true, memory_id: memoryId };
57
+ }
58
+ });
59
+
60
+ // memory_search tool
61
+ tools.register({
62
+ name: 'memory_search',
63
+ description: 'Search memories by query',
64
+ schema: {
65
+ type: 'object',
66
+ properties: {
67
+ query: { type: 'string' },
68
+ limit: { type: 'number', default: 10 }
69
+ },
70
+ required: ['query']
71
+ },
72
+ handler: async (params: any) => {
73
+ const { query, limit = 10 } = params;
74
+ const memories = db.prepare(`
75
+ SELECT id, summary, importance, created_at
76
+ FROM memories
77
+ WHERE summary LIKE ?
78
+ ORDER BY importance DESC
79
+ LIMIT ?
80
+ `).all(`%${query}%`, limit);
81
+
82
+ return { memories };
83
+ }
84
+ });
85
+
86
+ // memory_summary tool
87
+ tools.register({
88
+ name: 'memory_summary',
89
+ description: 'Get memory summary for time period',
90
+ schema: {
91
+ type: 'object',
92
+ properties: {
93
+ period: { type: 'string', enum: ['day', 'week', 'month'] },
94
+ date: { type: 'string' }
95
+ },
96
+ required: ['period']
97
+ },
98
+ handler: async (params: any) => {
99
+ const { period } = params;
100
+ const today = new Date();
101
+ let startDate: Date;
102
+
103
+ switch (period) {
104
+ case 'day':
105
+ startDate = today;
106
+ break;
107
+ case 'week':
108
+ startDate = new Date(today);
109
+ startDate.setDate(today.getDate() - today.getDay());
110
+ break;
111
+ case 'month':
112
+ startDate = new Date(today.getFullYear(), today.getMonth(), 1);
113
+ break;
114
+ default:
115
+ startDate = today;
116
+ }
117
+
118
+ const startDateStr = startDate.toISOString().split('T')[0];
119
+
120
+ const memories = db.prepare(`
121
+ SELECT summary, importance, created_at
122
+ FROM memories
123
+ WHERE date(created_at) >= date(?)
124
+ ORDER BY importance DESC
125
+ LIMIT 20
126
+ `).all(startDateStr);
127
+
128
+ const count = Array.isArray(memories) ? memories.length : 0;
129
+
130
+ return {
131
+ period,
132
+ count,
133
+ memories: Array.isArray(memories) ? memories.slice(0, 10) : []
134
+ };
135
+ }
136
+ });
137
+ }
package/src/types.ts ADDED
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Claw-Memory Type Definitions
3
+ * Lightweight AI memory system for OpenClaw and Claude Code
4
+ */
5
+
6
+ export interface IntegratedSummary {
7
+ active_areas: string[];
8
+ key_topics: string[];
9
+ recent_summary: string;
10
+ }
11
+
12
+ export interface Memory {
13
+ id: string;
14
+ contentPath: string;
15
+ summary: string | null;
16
+ integratedSummary: IntegratedSummary | null;
17
+ createdAt: Date;
18
+ updatedAt: Date;
19
+ tokenCount: number;
20
+ importance: number;
21
+ accessCount: number;
22
+ lastAccessedAt: Date | null;
23
+ isArchived: boolean;
24
+ isDuplicate: boolean;
25
+ duplicateOf: string | null;
26
+ }
27
+
28
+ export interface Entity {
29
+ id: string;
30
+ name: string;
31
+ type: 'keyword' | 'tag' | 'subject' | 'person' | 'project';
32
+ parentId: string | null;
33
+ level: number;
34
+ embedding: Buffer | null;
35
+ metadata: Record<string, unknown> | null;
36
+ createdAt: Date;
37
+ }
38
+
39
+ export interface MemoryEntity {
40
+ memoryId: string;
41
+ entityId: string;
42
+ relevance: number;
43
+ source: 'auto' | 'manual';
44
+ createdAt: Date;
45
+ }
46
+
47
+ export interface EntityRelation {
48
+ id: string;
49
+ sourceId: string;
50
+ targetId: string;
51
+ relationType: 'related' | 'parent' | 'similar' | 'co_occur';
52
+ weight: number;
53
+ evidenceCount: number;
54
+ createdAt: Date;
55
+ }
56
+
57
+ export interface TimeBucket {
58
+ date: string; // YYYY-MM-DD
59
+ memoryCount: number;
60
+ summary: string | null;
61
+ summaryGeneratedAt: Date | null;
62
+ keyTopics: string[] | null;
63
+ createdAt: Date;
64
+ }
65
+
66
+ export interface SaveMemoryInput {
67
+ content: string;
68
+ metadata: {
69
+ tags?: string[];
70
+ subjects?: string[];
71
+ keywords?: string[];
72
+ importance?: number;
73
+ summary?: string;
74
+ };
75
+ userId?: string;
76
+ }
77
+
78
+ export interface SearchMemoryInput {
79
+ query: string;
80
+ timeRange?: 'today' | 'week' | 'month' | 'year' | 'all';
81
+ tags?: string[];
82
+ limit?: number;
83
+ maxTokens?: number;
84
+ }
85
+
86
+ export interface GetContextInput {
87
+ query: string;
88
+ maxTokens?: number;
89
+ }
90
+
91
+ export interface GetSummaryInput {
92
+ period: 'day' | 'week' | 'month';
93
+ date?: string;
94
+ }
95
+
96
+ export interface WeeklyReport {
97
+ // 1. 基础统计
98
+ period: { start: string; end: string };
99
+ basic: {
100
+ totalMemories: number;
101
+ totalTokens: number;
102
+ avgImportance: number;
103
+ };
104
+
105
+ // 2. 标签分布维度
106
+ tags: {
107
+ topTags: { name: string; count: number }[];
108
+ tagDistribution: Record<string, number>;
109
+ };
110
+
111
+ // 3. 主题/关键词维度
112
+ topics: {
113
+ keywords: { word: string; count: number }[];
114
+ keyTopics: string[];
115
+ };
116
+
117
+ // 4. 重要性维度
118
+ importance: {
119
+ highPriority: Pick<Memory, 'id' | 'summary' | 'importance'>[];
120
+ mediumPriority: Pick<Memory, 'id' | 'summary' | 'importance'>[];
121
+ lowPriority: Pick<Memory, 'id' | 'summary' | 'importance'>[];
122
+ };
123
+
124
+ // 5. 访问模式维度
125
+ access: {
126
+ mostAccessed: Pick<Memory, 'id' | 'summary' | 'accessCount'>[];
127
+ recentlyCreated: Pick<Memory, 'id' | 'summary' | 'createdAt'>[];
128
+ recentlyAccessed: Pick<Memory, 'id' | 'summary' | 'lastAccessedAt'>[];
129
+ };
130
+
131
+ // 6. 实体关系维度
132
+ entities: {
133
+ relatedGroups: { entity: string; related: string[] }[];
134
+ coOccurringTags: [string, string][];
135
+ };
136
+
137
+ // 7. LLM 智能总结
138
+ summary: string;
139
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "resolveJsonModule": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist", "tests"]
20
+ }
@@ -0,0 +1,16 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: ['test/**/*.test.ts'],
8
+ testTimeout: 60000,
9
+ pool: 'forks',
10
+ poolOptions: {
11
+ forks: {
12
+ singleFork: true,
13
+ },
14
+ },
15
+ },
16
+ });