@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.
- package/.claude/settings.local.json +68 -0
- package/README.md +323 -0
- package/dist/config/llm.d.ts +13 -0
- package/dist/config/llm.d.ts.map +1 -0
- package/dist/config/llm.js +96 -0
- package/dist/config/llm.js.map +1 -0
- package/dist/config/plugin.d.ts +15 -0
- package/dist/config/plugin.d.ts.map +1 -0
- package/dist/config/plugin.js +32 -0
- package/dist/config/plugin.js.map +1 -0
- package/dist/db/entityRepository.d.ts +21 -0
- package/dist/db/entityRepository.d.ts.map +1 -0
- package/dist/db/entityRepository.js +55 -0
- package/dist/db/entityRepository.js.map +1 -0
- package/dist/db/repository.d.ts +22 -0
- package/dist/db/repository.d.ts.map +1 -0
- package/dist/db/repository.js +77 -0
- package/dist/db/repository.js.map +1 -0
- package/dist/db/schema.d.ts +5 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +112 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/todoRepository.d.ts +26 -0
- package/dist/db/todoRepository.d.ts.map +1 -0
- package/dist/db/todoRepository.js +54 -0
- package/dist/db/todoRepository.js.map +1 -0
- package/dist/hooks/bootstrap.d.ts +3 -0
- package/dist/hooks/bootstrap.d.ts.map +1 -0
- package/dist/hooks/bootstrap.js +28 -0
- package/dist/hooks/bootstrap.js.map +1 -0
- package/dist/hooks/message.d.ts +18 -0
- package/dist/hooks/message.d.ts.map +1 -0
- package/dist/hooks/message.js +52 -0
- package/dist/hooks/message.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/tools.d.ts +26 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +360 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/plugin.d.ts +18 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +62 -0
- package/dist/plugin.js.map +1 -0
- package/dist/services/entityGraphService.d.ts +87 -0
- package/dist/services/entityGraphService.d.ts.map +1 -0
- package/dist/services/entityGraphService.js +271 -0
- package/dist/services/entityGraphService.js.map +1 -0
- package/dist/services/memory.d.ts +26 -0
- package/dist/services/memory.d.ts.map +1 -0
- package/dist/services/memory.js +281 -0
- package/dist/services/memory.js.map +1 -0
- package/dist/services/memoryIndex.d.ts +34 -0
- package/dist/services/memoryIndex.d.ts.map +1 -0
- package/dist/services/memoryIndex.js +100 -0
- package/dist/services/memoryIndex.js.map +1 -0
- package/dist/services/metadataExtractor.d.ts +16 -0
- package/dist/services/metadataExtractor.d.ts.map +1 -0
- package/dist/services/metadataExtractor.js +75 -0
- package/dist/services/metadataExtractor.js.map +1 -0
- package/dist/services/retrieval.d.ts +24 -0
- package/dist/services/retrieval.d.ts.map +1 -0
- package/dist/services/retrieval.js +40 -0
- package/dist/services/retrieval.js.map +1 -0
- package/dist/services/scheduler.d.ts +122 -0
- package/dist/services/scheduler.d.ts.map +1 -0
- package/dist/services/scheduler.js +434 -0
- package/dist/services/scheduler.js.map +1 -0
- package/dist/services/summarizer.d.ts +43 -0
- package/dist/services/summarizer.d.ts.map +1 -0
- package/dist/services/summarizer.js +252 -0
- package/dist/services/summarizer.js.map +1 -0
- package/dist/services/tagService.d.ts +64 -0
- package/dist/services/tagService.d.ts.map +1 -0
- package/dist/services/tagService.js +281 -0
- package/dist/services/tagService.js.map +1 -0
- package/dist/tools/memory.d.ts +3 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +114 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/types.d.ts +128 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/plans/2026-03-02-claw-memory-design.md +445 -0
- package/docs/plans/2026-03-02-incremental-summary-design.md +157 -0
- package/docs/plans/2026-03-02-incremental-summary-implementation.md +468 -0
- package/docs/plans/2026-03-02-memory-index-design.md +163 -0
- package/docs/plans/2026-03-02-memory-index-implementation.md +836 -0
- package/docs/plans/2026-03-02-mvp-implementation.md +1703 -0
- package/docs/plans/2026-03-02-testing-implementation.md +395 -0
- package/docs/plans/2026-03-02-testing-plan.md +93 -0
- package/docs/plans/2026-03-03-claw-memory-openclaw-plugin-design.md +285 -0
- package/docs/plans/2026-03-03-claw-memory-plugin-implementation.md +642 -0
- package/docs/plans/2026-03-03-entity-graph-design.md +121 -0
- package/docs/plans/2026-03-03-entity-graph-implementation.md +687 -0
- package/docs/plans/2026-03-03-llm-generic-config-design.md +43 -0
- package/docs/plans/2026-03-03-llm-generic-config-implementation.md +186 -0
- package/docs/plans/2026-03-03-memory-e2e-stress-test-design.md +110 -0
- package/docs/plans/2026-03-03-memory-e2e-stress-test-implementation.md +464 -0
- package/docs/plans/2026-03-03-minimax-llm-fix.md +156 -0
- package/docs/plans/2026-03-03-scheduler-design.md +165 -0
- package/docs/plans/2026-03-03-scheduler-implementation.md +777 -0
- package/docs/plans/2026-03-03-tags-visualization-design.md +73 -0
- package/docs/plans/2026-03-03-tags-visualization-implementation.md +539 -0
- package/openclaw.plugin.json +11 -0
- package/package.json +41 -0
- package/src/config/llm.ts +129 -0
- package/src/config/plugin.ts +47 -0
- package/src/db/entityRepository.ts +80 -0
- package/src/db/repository.ts +106 -0
- package/src/db/schema.ts +121 -0
- package/src/db/todoRepository.ts +76 -0
- package/src/hooks/bootstrap.ts +36 -0
- package/src/hooks/message.ts +84 -0
- package/src/index.ts +50 -0
- package/src/plugin.ts +85 -0
- package/src/services/entityGraphService.ts +367 -0
- package/src/services/memory.ts +338 -0
- package/src/services/memoryIndex.ts +140 -0
- package/src/services/metadataExtractor.ts +89 -0
- package/src/services/retrieval.ts +71 -0
- package/src/services/scheduler.ts +529 -0
- package/src/services/summarizer.ts +318 -0
- package/src/services/tagService.ts +335 -0
- package/src/tools/memory.ts +137 -0
- package/src/types.ts +139 -0
- package/tsconfig.json +20 -0
- 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
|
+
}
|
package/vitest.config.ts
ADDED
|
@@ -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
|
+
});
|