@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 @@
1
+ {"version":3,"file":"entityRepository.js","sourceRoot":"","sources":["../../src/db/entityRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import Database from 'better-sqlite3';
2
+ import type { Memory, IntegratedSummary } from '../types.js';
3
+ export interface CreateMemoryInput {
4
+ contentPath: string;
5
+ summary?: string;
6
+ integratedSummary?: IntegratedSummary;
7
+ importance?: number;
8
+ tokenCount?: number;
9
+ }
10
+ export declare class MemoryRepository {
11
+ private db;
12
+ constructor(db: Database.Database);
13
+ create(input: CreateMemoryInput): Memory;
14
+ findById(id: string): Memory | null;
15
+ findAll(limit?: number, offset?: number): Memory[];
16
+ delete(id: string): boolean;
17
+ updateLastAccessed(id: string): void;
18
+ private mapRowToMemory;
19
+ private safeParseJSON;
20
+ getLatestIntegratedSummary(): IntegratedSummary | null;
21
+ }
22
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/db/repository.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,EAAE,CAAoB;gBAElB,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAIjC,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM;IAqBxC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IASnC,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAWlD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAK3B,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAMpC,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,aAAa;IAQrB,0BAA0B,IAAI,iBAAiB,GAAG,IAAI;CAQvD"}
@@ -0,0 +1,77 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ export class MemoryRepository {
3
+ db;
4
+ constructor(db) {
5
+ this.db = db;
6
+ }
7
+ create(input) {
8
+ const id = uuidv4();
9
+ const now = new Date();
10
+ this.db.prepare(`
11
+ INSERT INTO memories (id, content_path, summary, integrated_summary, importance, token_count, created_at, updated_at)
12
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
13
+ `).run(id, input.contentPath, input.summary || null, input.integratedSummary ? JSON.stringify(input.integratedSummary) : null, input.importance ?? 0.5, input.tokenCount ?? 0, now.toISOString(), now.toISOString());
14
+ return this.findById(id);
15
+ }
16
+ findById(id) {
17
+ const row = this.db.prepare(`
18
+ SELECT * FROM memories WHERE id = ?
19
+ `).get(id);
20
+ if (!row)
21
+ return null;
22
+ return this.mapRowToMemory(row);
23
+ }
24
+ findAll(limit, offset) {
25
+ let query = 'SELECT * FROM memories ORDER BY created_at DESC';
26
+ if (limit) {
27
+ query += ` LIMIT ${limit}`;
28
+ if (offset)
29
+ query += ` OFFSET ${offset}`;
30
+ }
31
+ const rows = this.db.prepare(query).all();
32
+ return rows.map(row => this.mapRowToMemory(row));
33
+ }
34
+ delete(id) {
35
+ const result = this.db.prepare('DELETE FROM memories WHERE id = ?').run(id);
36
+ return result.changes > 0;
37
+ }
38
+ updateLastAccessed(id) {
39
+ this.db.prepare(`
40
+ UPDATE memories SET last_accessed_at = ?, access_count = access_count + 1 WHERE id = ?
41
+ `).run(new Date().toISOString(), id);
42
+ }
43
+ mapRowToMemory(row) {
44
+ return {
45
+ id: row.id,
46
+ contentPath: row.content_path,
47
+ summary: row.summary,
48
+ integratedSummary: row.integrated_summary ? this.safeParseJSON(row.integrated_summary) : null,
49
+ createdAt: new Date(row.created_at),
50
+ updatedAt: new Date(row.updated_at),
51
+ tokenCount: row.token_count,
52
+ importance: row.importance,
53
+ accessCount: row.access_count,
54
+ lastAccessedAt: row.last_accessed_at ? new Date(row.last_accessed_at) : null,
55
+ isArchived: Boolean(row.is_archived),
56
+ isDuplicate: Boolean(row.is_duplicate),
57
+ duplicateOf: row.duplicate_of
58
+ };
59
+ }
60
+ safeParseJSON(json) {
61
+ try {
62
+ return JSON.parse(json);
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ getLatestIntegratedSummary() {
69
+ const row = this.db.prepare(`
70
+ SELECT integrated_summary FROM memories ORDER BY created_at DESC LIMIT 1
71
+ `).get();
72
+ if (!row || !row.integrated_summary)
73
+ return null;
74
+ return this.safeParseJSON(row.integrated_summary);
75
+ }
76
+ }
77
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/db/repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import Database from 'better-sqlite3';
2
+ export declare function initializeDatabase(db: Database.Database): void;
3
+ export declare function resetDbInstance(): void;
4
+ export declare function getDatabase(dbPath?: string): Database.Database;
5
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAqG9D;AAID,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED,wBAAgB,WAAW,CAAC,MAAM,GAAE,MAA+B,GAAG,QAAQ,CAAC,QAAQ,CAMtF"}
@@ -0,0 +1,112 @@
1
+ import Database from 'better-sqlite3';
2
+ export function initializeDatabase(db) {
3
+ // 1. 记忆表
4
+ db.exec(`
5
+ CREATE TABLE IF NOT EXISTS memories (
6
+ id TEXT PRIMARY KEY,
7
+ content_path TEXT NOT NULL,
8
+ summary TEXT,
9
+ integrated_summary JSON,
10
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
11
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
12
+ token_count INTEGER DEFAULT 0,
13
+ importance REAL DEFAULT 0.5,
14
+ access_count INTEGER DEFAULT 0,
15
+ last_accessed_at TIMESTAMP,
16
+ is_archived BOOLEAN DEFAULT FALSE,
17
+ is_duplicate BOOLEAN DEFAULT FALSE,
18
+ duplicate_of TEXT
19
+ )
20
+ `);
21
+ // 2. 实体表
22
+ db.exec(`
23
+ CREATE TABLE IF NOT EXISTS entities (
24
+ id TEXT PRIMARY KEY,
25
+ name TEXT NOT NULL,
26
+ type TEXT NOT NULL,
27
+ parent_id TEXT,
28
+ level INTEGER DEFAULT 0,
29
+ embedding BLOB,
30
+ metadata JSON,
31
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
32
+ FOREIGN KEY (parent_id) REFERENCES entities(id)
33
+ )
34
+ `);
35
+ // 3. 记忆-实体关联表
36
+ db.exec(`
37
+ CREATE TABLE IF NOT EXISTS memory_entities (
38
+ memory_id TEXT NOT NULL,
39
+ entity_id TEXT NOT NULL,
40
+ relevance REAL DEFAULT 1.0,
41
+ source TEXT DEFAULT 'auto',
42
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
43
+ PRIMARY KEY (memory_id, entity_id),
44
+ FOREIGN KEY (memory_id) REFERENCES memories(id),
45
+ FOREIGN KEY (entity_id) REFERENCES entities(id)
46
+ )
47
+ `);
48
+ // 4. 实体关系图
49
+ db.exec(`
50
+ CREATE TABLE IF NOT EXISTS entity_relations (
51
+ id TEXT PRIMARY KEY,
52
+ source_id TEXT NOT NULL,
53
+ target_id TEXT NOT NULL,
54
+ relation_type TEXT NOT NULL,
55
+ weight REAL DEFAULT 1.0,
56
+ evidence_count INTEGER DEFAULT 1,
57
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
58
+ FOREIGN KEY (source_id) REFERENCES entities(id),
59
+ FOREIGN KEY (target_id) REFERENCES entities(id),
60
+ UNIQUE(source_id, target_id, relation_type)
61
+ )
62
+ `);
63
+ // 5. 时间桶
64
+ db.exec(`
65
+ CREATE TABLE IF NOT EXISTS time_buckets (
66
+ date TEXT PRIMARY KEY,
67
+ memory_count INTEGER DEFAULT 0,
68
+ summary TEXT,
69
+ summary_generated_at TIMESTAMP,
70
+ key_topics JSON,
71
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
72
+ )
73
+ `);
74
+ // 6. 待办事项
75
+ db.exec(`
76
+ CREATE TABLE IF NOT EXISTS todos (
77
+ id TEXT PRIMARY KEY,
78
+ content TEXT NOT NULL,
79
+ period TEXT NOT NULL,
80
+ period_date TEXT,
81
+ created_at TEXT NOT NULL,
82
+ completed_at TEXT,
83
+ memory_id TEXT
84
+ )
85
+ `);
86
+ // 创建索引
87
+ db.exec(`
88
+ CREATE INDEX IF NOT EXISTS idx_memories_created ON memories(created_at);
89
+ CREATE INDEX IF NOT EXISTS idx_memories_importance ON memories(importance);
90
+ CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name);
91
+ CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
92
+ CREATE INDEX IF NOT EXISTS idx_entities_parent ON entities(parent_id);
93
+ CREATE INDEX IF NOT EXISTS idx_memory_entities_entity ON memory_entities(entity_id);
94
+ CREATE INDEX IF NOT EXISTS idx_entity_relations_source ON entity_relations(source_id);
95
+ CREATE INDEX IF NOT EXISTS idx_entity_relations_target ON entity_relations(target_id);
96
+ `);
97
+ }
98
+ let dbInstance = null;
99
+ export function resetDbInstance() {
100
+ if (dbInstance) {
101
+ dbInstance.close();
102
+ dbInstance = null;
103
+ }
104
+ }
105
+ export function getDatabase(dbPath = './memories/memory.db') {
106
+ if (!dbInstance) {
107
+ dbInstance = new Database(dbPath);
108
+ initializeDatabase(dbInstance);
109
+ }
110
+ return dbInstance;
111
+ }
112
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,MAAM,UAAU,kBAAkB,CAAC,EAAqB;IACtD,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;GAgBP,CAAC,CAAC;IAEH,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;GAYP,CAAC,CAAC;IAEH,cAAc;IACd,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;GAWP,CAAC,CAAC;IAEH,WAAW;IACX,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;GAaP,CAAC,CAAC;IAEH,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;;;;;;;;;GASP,CAAC,CAAC;IAEH,UAAU;IACV,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;GAUP,CAAC,CAAC;IAEH,OAAO;IACP,EAAE,CAAC,IAAI,CAAC;;;;;;;;;GASP,CAAC,CAAC;AACL,CAAC;AAED,IAAI,UAAU,GAA6B,IAAI,CAAC;AAEhD,MAAM,UAAU,eAAe;IAC7B,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAiB,sBAAsB;IACjE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,UAAU,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAClC,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import Database from 'better-sqlite3';
2
+ export interface Todo {
3
+ id: string;
4
+ content: string;
5
+ period: 'day' | 'week' | 'month';
6
+ periodDate: string;
7
+ createdAt: Date;
8
+ completedAt: Date | null;
9
+ memoryId: string | null;
10
+ }
11
+ export interface CreateTodoInput {
12
+ content: string;
13
+ period: 'day' | 'week' | 'month';
14
+ periodDate: string;
15
+ memoryId?: string;
16
+ }
17
+ export declare class TodoRepository {
18
+ private db;
19
+ constructor(db: Database.Database);
20
+ create(input: CreateTodoInput): Todo;
21
+ findByPeriod(period: string, periodDate: string, includeCompleted?: boolean): Todo[];
22
+ findById(id: string): Todo | null;
23
+ markCompleted(id: string): void;
24
+ private mapRowToTodo;
25
+ }
26
+ //# sourceMappingURL=todoRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todoRepository.d.ts","sourceRoot":"","sources":["../../src/db/todoRepository.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAoBpC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,UAAQ,GAAG,IAAI,EAAE;IASlF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAMjC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAM/B,OAAO,CAAC,YAAY;CAWrB"}
@@ -0,0 +1,54 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ export class TodoRepository {
3
+ db;
4
+ constructor(db) {
5
+ this.db = db;
6
+ }
7
+ create(input) {
8
+ const id = uuidv4();
9
+ const createdAt = new Date().toISOString();
10
+ this.db.prepare(`
11
+ INSERT INTO todos (id, content, period, period_date, created_at, memory_id)
12
+ VALUES (?, ?, ?, ?, ?, ?)
13
+ `).run(id, input.content, input.period, input.periodDate, createdAt, input.memoryId || null);
14
+ return {
15
+ id,
16
+ content: input.content,
17
+ period: input.period,
18
+ periodDate: input.periodDate,
19
+ createdAt: new Date(createdAt),
20
+ completedAt: null,
21
+ memoryId: input.memoryId || null
22
+ };
23
+ }
24
+ findByPeriod(period, periodDate, includeCompleted = false) {
25
+ const sql = includeCompleted
26
+ ? `SELECT * FROM todos WHERE period = ? AND period_date = ? ORDER BY created_at DESC`
27
+ : `SELECT * FROM todos WHERE period = ? AND period_date = ? AND completed_at IS NULL ORDER BY created_at DESC`;
28
+ const rows = this.db.prepare(sql).all(period, periodDate);
29
+ return rows.map(this.mapRowToTodo);
30
+ }
31
+ findById(id) {
32
+ const row = this.db.prepare('SELECT * FROM todos WHERE id = ?').get(id);
33
+ if (!row)
34
+ return null;
35
+ return this.mapRowToTodo(row);
36
+ }
37
+ markCompleted(id) {
38
+ this.db.prepare(`
39
+ UPDATE todos SET completed_at = ? WHERE id = ?
40
+ `).run(new Date().toISOString(), id);
41
+ }
42
+ mapRowToTodo(row) {
43
+ return {
44
+ id: row.id,
45
+ content: row.content,
46
+ period: row.period,
47
+ periodDate: row.period_date,
48
+ createdAt: new Date(row.created_at),
49
+ completedAt: row.completed_at ? new Date(row.completed_at) : null,
50
+ memoryId: row.memory_id
51
+ };
52
+ }
53
+ }
54
+ //# sourceMappingURL=todoRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todoRepository.js","sourceRoot":"","sources":["../../src/db/todoRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAmBpC,MAAM,OAAO,cAAc;IACL;IAApB,YAAoB,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;IAAG,CAAC;IAE7C,MAAM,CAAC,KAAsB;QAC3B,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE3C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGf,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;QAE7F,OAAO;YACL,EAAE;YACF,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC;YAC9B,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;SACjC,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,MAAc,EAAE,UAAkB,EAAE,gBAAgB,GAAG,KAAK;QACvE,MAAM,GAAG,GAAG,gBAAgB;YAC1B,CAAC,CAAC,mFAAmF;YACrF,CAAC,CAAC,4GAA4G,CAAC;QAEjH,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAU,CAAC;QACnE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrC,CAAC;IAED,QAAQ,CAAC,EAAU;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAQ,CAAC;QAC/E,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,aAAa,CAAC,EAAU;QACtB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;KAEf,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAEO,YAAY,CAAC,GAAQ;QAC3B,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACnC,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;YACjE,QAAQ,EAAE,GAAG,CAAC,SAAS;SACxB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ import type { Database } from 'better-sqlite3';
2
+ export declare function handleAgentBootstrap(db: Database): Promise<string>;
3
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/hooks/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC,MAAM,CAAC,CA+BjB"}
@@ -0,0 +1,28 @@
1
+ export async function handleAgentBootstrap(db) {
2
+ // 获取本周记忆摘要
3
+ const today = new Date();
4
+ const weekStart = new Date(today);
5
+ weekStart.setDate(today.getDate() - today.getDay());
6
+ const weekStartStr = weekStart.toISOString().split('T')[0];
7
+ const weekMemories = db.prepare(`
8
+ SELECT summary, importance
9
+ FROM memories
10
+ WHERE date(created_at) >= date(?)
11
+ ORDER BY importance DESC
12
+ LIMIT 10
13
+ `).all(weekStartStr);
14
+ if (weekMemories.length === 0) {
15
+ return '';
16
+ }
17
+ // 构建摘要文本
18
+ const lines = ['## 记忆摘要\n'];
19
+ lines.push(`本周共有 ${weekMemories.length} 条记忆记录。\n`);
20
+ lines.push('### 重点内容:\n');
21
+ for (const m of weekMemories.slice(0, 5)) {
22
+ if (m.summary) {
23
+ lines.push(`- ${m.summary}`);
24
+ }
25
+ }
26
+ return lines.join('\n');
27
+ }
28
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/hooks/bootstrap.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAY;IAEZ,WAAW;IACX,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3D,MAAM,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;GAM/B,CAAC,CAAC,GAAG,CAAC,YAAY,CAA8C,CAAC;IAElE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,SAAS;IACT,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,QAAQ,YAAY,CAAC,MAAM,WAAW,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE1B,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Database } from 'better-sqlite3';
2
+ interface MessageEvent {
3
+ message: {
4
+ role: 'user' | 'assistant';
5
+ content: string;
6
+ };
7
+ session: {
8
+ id: string;
9
+ key: string;
10
+ };
11
+ conversation?: Array<{
12
+ role: 'user' | 'assistant';
13
+ content: string;
14
+ }>;
15
+ }
16
+ export declare function handleMessageSent(event: MessageEvent, db: Database, dataDir: string): Promise<void>;
17
+ export {};
18
+ //# sourceMappingURL=message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/hooks/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM/C,UAAU,YAAY;IACpB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,YAAY,CAAC,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,YAAY,EACnB,EAAE,EAAE,QAAQ,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA0Df"}
@@ -0,0 +1,52 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import * as path from 'path';
3
+ import * as fs from 'fs';
4
+ import { homedir } from 'os';
5
+ export async function handleMessageSent(event, db, dataDir) {
6
+ // 只处理 assistant 消息(AI 回复后保存)
7
+ if (event.message.role !== 'assistant') {
8
+ return;
9
+ }
10
+ // 从 conversation 中获取最后一条 user 消息
11
+ let userMessage = '';
12
+ if (event.conversation && event.conversation.length > 0) {
13
+ // 找到最后一个 user 消息
14
+ for (let i = event.conversation.length - 1; i >= 0; i--) {
15
+ if (event.conversation[i].role === 'user') {
16
+ userMessage = event.conversation[i].content;
17
+ break;
18
+ }
19
+ }
20
+ }
21
+ const assistantMessage = event.message.content;
22
+ if (!userMessage || !assistantMessage) {
23
+ console.log('[ClawMemory] Skipping - no valid Q&A pair');
24
+ return;
25
+ }
26
+ // 构建 Q&A
27
+ const qaContent = `Q: ${userMessage}\n\nA: ${assistantMessage}`;
28
+ // 解析 dataDir 中的 ~
29
+ const resolvedDataDir = dataDir.replace(/^~/, homedir());
30
+ // 确保目录存在
31
+ if (!fs.existsSync(resolvedDataDir)) {
32
+ fs.mkdirSync(resolvedDataDir, { recursive: true });
33
+ }
34
+ const memoriesDir = path.join(resolvedDataDir, 'memories');
35
+ if (!fs.existsSync(memoriesDir)) {
36
+ fs.mkdirSync(memoriesDir, { recursive: true });
37
+ }
38
+ // 保存记忆
39
+ const memoryId = uuidv4();
40
+ const contentPath = path.join(memoriesDir, `${memoryId}.md`);
41
+ // 写入文件
42
+ fs.writeFileSync(contentPath, qaContent, 'utf-8');
43
+ // 提取摘要(取前200字符)
44
+ const summary = assistantMessage.substring(0, 200);
45
+ // 插入数据库
46
+ db.prepare(`
47
+ INSERT INTO memories (id, content_path, summary, created_at)
48
+ VALUES (?, ?, ?, datetime('now'))
49
+ `).run(memoryId, contentPath, summary);
50
+ console.log(`[ClawMemory] Saved memory: ${memoryId}`);
51
+ }
52
+ //# sourceMappingURL=message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/hooks/message.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAiB7B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAmB,EACnB,EAAY,EACZ,OAAe;IAEf,6BAA6B;IAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACvC,OAAO;IACT,CAAC;IAED,iCAAiC;IACjC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,iBAAiB;QACjB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACxD,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1C,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;gBAC5C,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;IAE/C,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO;IACT,CAAC;IAED,SAAS;IACT,MAAM,SAAS,GAAG,MAAM,WAAW,UAAU,gBAAgB,EAAE,CAAC;IAEhE,kBAAkB;IAClB,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAEzD,SAAS;IACT,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC3D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,OAAO;IACP,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC;IAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;IAE7D,OAAO;IACP,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAElD,gBAAgB;IAChB,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEnD,QAAQ;IACR,EAAE,CAAC,OAAO,CAAC;;;GAGV,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAEvC,OAAO,CAAC,GAAG,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { getDatabase } from './db/schema.js';
4
+ import { TagService } from './services/tagService.js';
5
+ import { writeFile } from 'fs/promises';
6
+ const program = new Command();
7
+ program
8
+ .name('claw-memory')
9
+ .description('OpenClaw 记忆插件 - CLI 工具')
10
+ .version('0.1.0');
11
+ program
12
+ .command('init')
13
+ .description('Initialize database')
14
+ .option('-d, --data-dir <dir>', 'Data directory', './memories')
15
+ .action((options) => {
16
+ const db = getDatabase(`${options.dataDir}/memory.db`);
17
+ console.log('Database initialized');
18
+ });
19
+ program
20
+ .command('tags <action>')
21
+ .description('标签管理命令')
22
+ .option('-o, --output <file>', '输出文件路径')
23
+ .option('-d, --data-dir <dir>', 'Data directory', './memories')
24
+ .action(async (action, options) => {
25
+ const db = getDatabase(`${options.dataDir}/memory.db`);
26
+ const tagService = new TagService(db);
27
+ const outputFile = options.output || (action === 'tree' ? 'tags-tree.html' : 'tags-stats.html');
28
+ if (action === 'tree') {
29
+ const data = await tagService.getTagTree();
30
+ const html = tagService.generateTreeHtml(data);
31
+ await writeFile(outputFile, html);
32
+ console.log(`标签树已生成: ${outputFile}`);
33
+ }
34
+ else if (action === 'stats') {
35
+ const stats = await tagService.getTagStats();
36
+ const html = tagService.generateStatsHtml(stats);
37
+ await writeFile(outputFile, html);
38
+ console.log(`标签统计已生成: ${outputFile}`);
39
+ }
40
+ else {
41
+ console.error('未知命令: tree 或 stats');
42
+ process.exit(1);
43
+ }
44
+ });
45
+ program.parse();
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,wBAAwB,CAAC;KACrC,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,qBAAqB,CAAC;KAClC,MAAM,CAAC,sBAAsB,EAAE,gBAAgB,EAAE,YAAY,CAAC;KAC9D,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;IAClB,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACtC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,QAAQ,CAAC;KACrB,MAAM,CAAC,qBAAqB,EAAE,QAAQ,CAAC;KACvC,MAAM,CAAC,sBAAsB,EAAE,gBAAgB,EAAE,YAAY,CAAC;KAC9D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;IAChC,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAEhG,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC;IACvC,CAAC;SAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,UAAU,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,YAAY,UAAU,EAAE,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { MemoryService } from '../services/memory.js';
2
+ import Database from 'better-sqlite3';
3
+ export interface MCPTool {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: {
7
+ type: 'object';
8
+ properties: Record<string, any>;
9
+ required?: string[];
10
+ };
11
+ handler: (params: any) => Promise<any>;
12
+ }
13
+ export declare function createSaveMemoryTool(memoryService: MemoryService): MCPTool;
14
+ export declare function createSearchMemoryTool(memoryService: MemoryService): MCPTool;
15
+ export declare function createGetContextTool(memoryService: MemoryService): MCPTool;
16
+ export declare function createGetSummaryTool(memoryService: MemoryService): MCPTool;
17
+ export declare function createListMemoriesTool(memoryService: MemoryService): MCPTool;
18
+ export declare function createDeleteMemoryTool(memoryService: MemoryService): MCPTool;
19
+ export declare function createGetMemoryIndexTool(db: Database.Database): MCPTool;
20
+ export declare function createAddTodoTool(db: Database.Database): MCPTool;
21
+ export declare function createListTodosTool(db: Database.Database): MCPTool;
22
+ export declare function createCompleteTodoTool(db: Database.Database): MCPTool;
23
+ export declare function createGetEntityRelationsTool(db: Database.Database): MCPTool;
24
+ export declare function createQueryEntityGraphTool(db: Database.Database): MCPTool;
25
+ export declare function createGetRelationStatsTool(db: Database.Database): MCPTool;
26
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAKtC,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACxC;AAED,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAyD1E;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CA6C5E;AAED,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAwB1E;AAED,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAwB1E;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAkC5E;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAkB5E;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAsBvE;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAoBhE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAmBlE;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAiBrE;AAED,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAoB3E;AAED,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAiCzE;AAED,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAczE"}