Skip to content

Commit c12ef3e

Browse files
catlog22claude
andcommitted
feat: 优化 core_memory MCP 工具,支持跨项目导出和精简列表输出
- 新增 findMemoryAcrossProjects 函数,支持按 CMEM-xxx ID 跨所有项目搜索记忆 - export 操作增强:当前项目找不到时自动搜索所有项目数据库 - list 操作优化:返回精简格式,preview 截断为 100 字符,减少输出体积 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 6eebdb8 commit c12ef3e

File tree

2 files changed

+91
-6
lines changed

2 files changed

+91
-6
lines changed

ccw/src/core/core-memory-store.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,55 @@ export function getMemoriesFromProject(projectId: string): CoreMemory[] {
13831383
}));
13841384
}
13851385

1386+
/**
1387+
* Find a memory by ID across all projects
1388+
* Searches through all project databases to locate a specific memory
1389+
*/
1390+
export function findMemoryAcrossProjects(memoryId: string): { memory: CoreMemory; projectId: string } | null {
1391+
const projectsDir = join(getCCWHome(), 'projects');
1392+
1393+
if (!existsSync(projectsDir)) {
1394+
return null;
1395+
}
1396+
1397+
const entries = readdirSync(projectsDir, { withFileTypes: true });
1398+
1399+
for (const entry of entries) {
1400+
if (!entry.isDirectory()) continue;
1401+
1402+
const projectId = entry.name;
1403+
const coreMemoryDb = join(projectsDir, projectId, 'core-memory', 'core_memory.db');
1404+
1405+
if (!existsSync(coreMemoryDb)) continue;
1406+
1407+
try {
1408+
const db = new Database(coreMemoryDb, { readonly: true });
1409+
const row = db.prepare('SELECT * FROM memories WHERE id = ?').get(memoryId) as any;
1410+
db.close();
1411+
1412+
if (row) {
1413+
return {
1414+
memory: {
1415+
id: row.id,
1416+
content: row.content,
1417+
summary: row.summary || '',
1418+
raw_output: row.raw_output,
1419+
created_at: row.created_at,
1420+
updated_at: row.updated_at,
1421+
archived: Boolean(row.archived),
1422+
metadata: row.metadata
1423+
},
1424+
projectId
1425+
};
1426+
}
1427+
} catch {
1428+
// Database might be locked or corrupted, skip
1429+
}
1430+
}
1431+
1432+
return null;
1433+
}
1434+
13861435
/**
13871436
* Export memories to a JSON file
13881437
*/

ccw/src/tools/core-memory.ts

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { z } from 'zod';
77
import type { ToolSchema, ToolResult } from '../types/tool.js';
8-
import { getCoreMemoryStore } from '../core/core-memory-store.js';
8+
import { getCoreMemoryStore, findMemoryAcrossProjects } from '../core/core-memory-store.js';
99
import * as MemoryEmbedder from '../core/memory-embedder-bridge.js';
1010
import { StoragePaths } from '../config/storage-paths.js';
1111
import { join } from 'path';
@@ -41,9 +41,17 @@ interface CoreMemory {
4141
updated_at: string;
4242
}
4343

44+
/** Compact memory info for list operation */
45+
interface CoreMemoryCompact {
46+
id: string;
47+
preview: string; // Truncated content/summary preview
48+
archived: boolean;
49+
updated_at: string;
50+
}
51+
4452
interface ListResult {
4553
operation: 'list';
46-
memories: CoreMemory[];
54+
memories: CoreMemoryCompact[];
4755
total: number;
4856
}
4957

@@ -112,18 +120,36 @@ function getDatabasePath(): string {
112120
return join(paths.root, 'core-memory', 'core_memory.db');
113121
}
114122

123+
/** Max preview length for list operation */
124+
const PREVIEW_MAX_LENGTH = 100;
125+
115126
/**
116127
* Operation: list
117-
* List all memories
128+
* List all memories with compact output
118129
*/
119130
function executeList(params: Params): ListResult {
120131
const { limit } = params;
121132
const store = getCoreMemoryStore(getProjectPath());
122133
const memories = store.getMemories({ limit }) as CoreMemory[];
123134

135+
// Convert to compact format with truncated preview
136+
const compactMemories: CoreMemoryCompact[] = memories.map((m) => {
137+
const source = m.summary || m.content;
138+
const preview = source.length > PREVIEW_MAX_LENGTH
139+
? source.substring(0, PREVIEW_MAX_LENGTH) + '...'
140+
: source;
141+
142+
return {
143+
id: m.id,
144+
preview,
145+
archived: m.archived,
146+
updated_at: m.updated_at,
147+
};
148+
});
149+
124150
return {
125151
operation: 'list',
126-
memories,
152+
memories: compactMemories,
127153
total: memories.length,
128154
};
129155
}
@@ -154,6 +180,7 @@ function executeImport(params: Params): ImportResult {
154180
/**
155181
* Operation: export
156182
* Export a memory as plain text
183+
* Searches current project first, then all projects if not found
157184
*/
158185
function executeExport(params: Params): ExportResult {
159186
const { id } = params;
@@ -162,11 +189,20 @@ function executeExport(params: Params): ExportResult {
162189
throw new Error('Parameter "id" is required for export operation');
163190
}
164191

192+
// Try current project first
165193
const store = getCoreMemoryStore(getProjectPath());
166-
const memory = store.getMemory(id);
194+
let memory = store.getMemory(id);
167195

196+
// If not found, search across all projects
168197
if (!memory) {
169-
throw new Error(`Memory "${id}" not found`);
198+
const result = findMemoryAcrossProjects(id);
199+
if (result) {
200+
memory = result.memory;
201+
}
202+
}
203+
204+
if (!memory) {
205+
throw new Error(`Memory "${id}" not found in any project`);
170206
}
171207

172208
return {

0 commit comments

Comments
 (0)