claude-session-continuity-mcp 1.0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +307 -0
  3. package/dist/dashboard-v2.d.ts +11 -0
  4. package/dist/dashboard-v2.js +1321 -0
  5. package/dist/dashboard.d.ts +2 -0
  6. package/dist/dashboard.js +1196 -0
  7. package/dist/db/database.d.ts +8 -0
  8. package/dist/db/database.js +208 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +3426 -0
  11. package/dist/schemas.d.ts +381 -0
  12. package/dist/schemas.js +119 -0
  13. package/dist/tools/context.d.ts +6 -0
  14. package/dist/tools/context.js +227 -0
  15. package/dist/tools/embedding.d.ts +5 -0
  16. package/dist/tools/embedding.js +191 -0
  17. package/dist/tools/feedback.d.ts +5 -0
  18. package/dist/tools/feedback.js +200 -0
  19. package/dist/tools/filter.d.ts +5 -0
  20. package/dist/tools/filter.js +169 -0
  21. package/dist/tools/index.d.ts +12 -0
  22. package/dist/tools/index.js +38 -0
  23. package/dist/tools/learning.d.ts +8 -0
  24. package/dist/tools/learning.js +395 -0
  25. package/dist/tools/memory.d.ts +8 -0
  26. package/dist/tools/memory.js +356 -0
  27. package/dist/tools/project.d.ts +9 -0
  28. package/dist/tools/project.js +396 -0
  29. package/dist/tools/relation.d.ts +4 -0
  30. package/dist/tools/relation.js +148 -0
  31. package/dist/tools/session.d.ts +7 -0
  32. package/dist/tools/session.js +272 -0
  33. package/dist/tools/solution.d.ts +5 -0
  34. package/dist/tools/solution.js +182 -0
  35. package/dist/tools/task.d.ts +6 -0
  36. package/dist/tools/task.js +184 -0
  37. package/dist/tools-v2/auto-capture.d.ts +5 -0
  38. package/dist/tools-v2/auto-capture.js +252 -0
  39. package/dist/tools-v2/context.d.ts +4 -0
  40. package/dist/tools-v2/context.js +170 -0
  41. package/dist/tools-v2/embedding.d.ts +3 -0
  42. package/dist/tools-v2/embedding.js +115 -0
  43. package/dist/tools-v2/index.d.ts +13 -0
  44. package/dist/tools-v2/index.js +73 -0
  45. package/dist/tools-v2/learn.d.ts +4 -0
  46. package/dist/tools-v2/learn.js +233 -0
  47. package/dist/tools-v2/memory.d.ts +6 -0
  48. package/dist/tools-v2/memory.js +340 -0
  49. package/dist/tools-v2/projects.d.ts +3 -0
  50. package/dist/tools-v2/projects.js +218 -0
  51. package/dist/tools-v2/task.d.ts +3 -0
  52. package/dist/tools-v2/task.js +193 -0
  53. package/dist/tools-v2/verify.d.ts +3 -0
  54. package/dist/tools-v2/verify.js +164 -0
  55. package/dist/types.d.ts +51 -0
  56. package/dist/types.js +7 -0
  57. package/dist/utils/auto-context.d.ts +58 -0
  58. package/dist/utils/auto-context.js +234 -0
  59. package/dist/utils/cache.d.ts +60 -0
  60. package/dist/utils/cache.js +161 -0
  61. package/dist/utils/embedding.d.ts +7 -0
  62. package/dist/utils/embedding.js +67 -0
  63. package/dist/utils/helpers.d.ts +4 -0
  64. package/dist/utils/helpers.js +45 -0
  65. package/dist/utils/logger.d.ts +17 -0
  66. package/dist/utils/logger.js +111 -0
  67. package/package.json +64 -0
@@ -0,0 +1,252 @@
1
+ // 자동 컨텍스트 캡처 도구
2
+ // session_start, session_end 도구로 세션 라이프사이클 관리
3
+ import { db } from '../db/database.js';
4
+ import { logger } from '../utils/logger.js';
5
+ import { loadContext, saveContext, createContextSnapshot, getCompactContext } from '../utils/auto-context.js';
6
+ import { invalidateProjects } from '../utils/cache.js';
7
+ import { z } from 'zod';
8
+ // ===== 스키마 =====
9
+ const SessionStartSchema = z.object({
10
+ project: z.string().min(1, 'project is required'),
11
+ compact: z.boolean().optional().default(false)
12
+ });
13
+ const SessionEndSchema = z.object({
14
+ project: z.string().min(1, 'project is required'),
15
+ currentState: z.string().min(1, 'currentState is required'),
16
+ recentFiles: z.array(z.string()).optional(),
17
+ blockers: z.string().optional(),
18
+ verification: z.enum(['passed', 'failed']).optional(),
19
+ architectureDecision: z.string().optional(),
20
+ codePattern: z.string().optional(),
21
+ techStack: z.record(z.string()).optional()
22
+ });
23
+ const SessionSummarySchema = z.object({
24
+ project: z.string().min(1, 'project is required')
25
+ });
26
+ // ===== 도구 정의 =====
27
+ export const autoCaptureTools = [
28
+ {
29
+ name: 'session_start',
30
+ description: `세션 시작 시 자동 컨텍스트 로드. 새 세션의 첫 도구 호출.
31
+ - 프로젝트 컨텍스트 자동 복원 (< 5ms 목표)
32
+ - compact=true: 토큰 효율적 요약 (~650토큰)
33
+ - compact=false: 전체 JSON 컨텍스트
34
+ 세션 시작 시 반드시 호출하여 연속성 확보.`,
35
+ inputSchema: {
36
+ type: 'object',
37
+ properties: {
38
+ project: { type: 'string', description: '프로젝트명' },
39
+ compact: { type: 'boolean', description: '간결한 요약 모드 (기본: false)', default: false }
40
+ },
41
+ required: ['project']
42
+ }
43
+ },
44
+ {
45
+ name: 'session_end',
46
+ description: `세션 종료 시 자동 컨텍스트 저장. 작업 완료 후 호출.
47
+ - currentState: 현재 상태 1줄 요약 (필수)
48
+ - recentFiles: 수정한 파일 목록 (최대 10개)
49
+ - blockers: 발견한 블로커/이슈
50
+ - verification: 마지막 검증 결과
51
+ - architectureDecision: 새로운 아키텍처 결정
52
+ - codePattern: 새로운 코드 패턴
53
+ - techStack: 기술 스택 업데이트
54
+ 다음 세션에서 이 컨텍스트가 자동 복원됨.`,
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {
58
+ project: { type: 'string', description: '프로젝트명' },
59
+ currentState: { type: 'string', description: '현재 상태 (1줄 요약)' },
60
+ recentFiles: { type: 'array', items: { type: 'string' }, description: '수정한 파일 목록' },
61
+ blockers: { type: 'string', description: '블로커/이슈' },
62
+ verification: { type: 'string', enum: ['passed', 'failed'], description: '검증 결과' },
63
+ architectureDecision: { type: 'string', description: '새 아키텍처 결정' },
64
+ codePattern: { type: 'string', description: '새 코드 패턴' },
65
+ techStack: { type: 'object', additionalProperties: { type: 'string' }, description: '기술 스택 업데이트' }
66
+ },
67
+ required: ['project', 'currentState']
68
+ }
69
+ },
70
+ {
71
+ name: 'session_summary',
72
+ description: `현재 프로젝트의 컨텍스트 요약 조회.
73
+ - 토큰 추정치 포함
74
+ - 전체 컨텍스트 스냅샷 반환
75
+ 세션 중간에 컨텍스트 확인 시 사용.`,
76
+ inputSchema: {
77
+ type: 'object',
78
+ properties: {
79
+ project: { type: 'string', description: '프로젝트명' }
80
+ },
81
+ required: ['project']
82
+ }
83
+ }
84
+ ];
85
+ // ===== 핸들러 =====
86
+ export async function handleSessionStart(args) {
87
+ return logger.withTool('session_start', async () => {
88
+ const parsed = SessionStartSchema.safeParse(args);
89
+ if (!parsed.success) {
90
+ return {
91
+ content: [{ type: 'text', text: `Validation error: ${parsed.error.message}` }],
92
+ isError: true
93
+ };
94
+ }
95
+ const { project, compact } = parsed.data;
96
+ const startTime = performance.now();
97
+ try {
98
+ // 세션 시작 기록
99
+ recordSessionStart(project);
100
+ if (compact) {
101
+ // 간결한 요약 반환
102
+ const summary = await getCompactContext(project);
103
+ const elapsed = performance.now() - startTime;
104
+ return {
105
+ content: [{
106
+ type: 'text',
107
+ text: `${summary}\n\n---\n_Loaded in ${elapsed.toFixed(2)}ms_`
108
+ }]
109
+ };
110
+ }
111
+ // 전체 컨텍스트 반환
112
+ const context = await loadContext(project);
113
+ const elapsed = performance.now() - startTime;
114
+ return {
115
+ content: [{
116
+ type: 'text',
117
+ text: JSON.stringify({
118
+ ...context,
119
+ _meta: {
120
+ loadTimeMs: parseFloat(elapsed.toFixed(2)),
121
+ timestamp: new Date().toISOString()
122
+ }
123
+ }, null, 2)
124
+ }]
125
+ };
126
+ }
127
+ catch (error) {
128
+ logger.error('Session start failed', { project, error: String(error) });
129
+ return {
130
+ content: [{ type: 'text', text: `Session start failed: ${error}` }],
131
+ isError: true
132
+ };
133
+ }
134
+ }, args);
135
+ }
136
+ export async function handleSessionEnd(args) {
137
+ return logger.withTool('session_end', async () => {
138
+ const parsed = SessionEndSchema.safeParse(args);
139
+ if (!parsed.success) {
140
+ return {
141
+ content: [{ type: 'text', text: `Validation error: ${parsed.error.message}` }],
142
+ isError: true
143
+ };
144
+ }
145
+ const { project, currentState, recentFiles, blockers, verification, architectureDecision, codePattern, techStack } = parsed.data;
146
+ try {
147
+ // 컨텍스트 저장
148
+ await saveContext(project, {
149
+ currentState,
150
+ recentFiles,
151
+ blockers,
152
+ verification,
153
+ architectureDecision,
154
+ codePattern,
155
+ techStack
156
+ });
157
+ // 세션 종료 기록
158
+ recordSessionEnd(project, currentState, verification);
159
+ // 스냅샷 생성 (토큰 추정 포함)
160
+ const snapshot = await createContextSnapshot(project);
161
+ return {
162
+ content: [{
163
+ type: 'text',
164
+ text: JSON.stringify({
165
+ success: true,
166
+ project,
167
+ saved: {
168
+ currentState,
169
+ recentFilesCount: recentFiles?.length || 0,
170
+ hasBlockers: !!blockers,
171
+ verification: verification || null,
172
+ newDecision: !!architectureDecision,
173
+ newPattern: !!codePattern,
174
+ techStackUpdated: !!techStack
175
+ },
176
+ tokenEstimate: snapshot.tokenEstimate,
177
+ timestamp: snapshot.timestamp
178
+ }, null, 2)
179
+ }]
180
+ };
181
+ }
182
+ catch (error) {
183
+ logger.error('Session end failed', { project, error: String(error) });
184
+ return {
185
+ content: [{ type: 'text', text: `Session end failed: ${error}` }],
186
+ isError: true
187
+ };
188
+ }
189
+ }, args);
190
+ }
191
+ export async function handleSessionSummary(args) {
192
+ return logger.withTool('session_summary', async () => {
193
+ const parsed = SessionSummarySchema.safeParse(args);
194
+ if (!parsed.success) {
195
+ return {
196
+ content: [{ type: 'text', text: `Validation error: ${parsed.error.message}` }],
197
+ isError: true
198
+ };
199
+ }
200
+ const { project } = parsed.data;
201
+ try {
202
+ const snapshot = await createContextSnapshot(project);
203
+ return {
204
+ content: [{
205
+ type: 'text',
206
+ text: JSON.stringify(snapshot, null, 2)
207
+ }]
208
+ };
209
+ }
210
+ catch (error) {
211
+ logger.error('Session summary failed', { project, error: String(error) });
212
+ return {
213
+ content: [{ type: 'text', text: `Session summary failed: ${error}` }],
214
+ isError: true
215
+ };
216
+ }
217
+ }, args);
218
+ }
219
+ // ===== 세션 기록 헬퍼 =====
220
+ function recordSessionStart(project) {
221
+ try {
222
+ const stmt = db.prepare(`
223
+ INSERT INTO sessions (project, last_work, current_status)
224
+ VALUES (?, 'Session started', 'in_progress')
225
+ `);
226
+ stmt.run(project);
227
+ invalidateProjects();
228
+ }
229
+ catch (error) {
230
+ logger.warn('Failed to record session start', { project, error: String(error) });
231
+ }
232
+ }
233
+ function recordSessionEnd(project, lastWork, verification) {
234
+ try {
235
+ // 마지막 in_progress 세션 업데이트
236
+ const stmt = db.prepare(`
237
+ UPDATE sessions
238
+ SET last_work = ?,
239
+ current_status = 'completed',
240
+ verification_result = ?,
241
+ timestamp = CURRENT_TIMESTAMP
242
+ WHERE project = ? AND current_status = 'in_progress'
243
+ ORDER BY id DESC
244
+ LIMIT 1
245
+ `);
246
+ stmt.run(lastWork, verification || null, project);
247
+ invalidateProjects();
248
+ }
249
+ catch (error) {
250
+ logger.warn('Failed to record session end', { project, error: String(error) });
251
+ }
252
+ }
@@ -0,0 +1,4 @@
1
+ import type { Tool, CallToolResult } from '../types.js';
2
+ export declare const contextTools: Tool[];
3
+ export declare function handleContextGet(args: unknown): Promise<CallToolResult>;
4
+ export declare function handleContextUpdate(args: unknown): Promise<CallToolResult>;
@@ -0,0 +1,170 @@
1
+ // 컨텍스트 도구 (context_get, context_update)
2
+ // 프로젝트 연속성의 핵심 - 세션 간 컨텍스트 유지
3
+ import * as path from 'path';
4
+ import { db, APPS_DIR } from '../db/database.js';
5
+ import { readFileContent, parseMarkdownTable } from '../utils/helpers.js';
6
+ import { logger } from '../utils/logger.js';
7
+ import { ContextGetSchema, ContextUpdateSchema } from '../schemas.js';
8
+ // ===== 도구 정의 =====
9
+ export const contextTools = [
10
+ {
11
+ name: 'context_get',
12
+ description: `프로젝트 컨텍스트 조회. 새 세션 시작 시 필수 호출.
13
+ - 고정 컨텍스트: 기술 스택, 아키텍처 결정, 코드 패턴
14
+ - 활성 컨텍스트: 현재 상태, 최근 파일, 블로커
15
+ - 미완료 태스크 (최대 3개)
16
+ ~650토큰으로 압축된 프로젝트 정보 반환.`,
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: {
20
+ project: { type: 'string', description: '프로젝트명' }
21
+ },
22
+ required: ['project']
23
+ }
24
+ },
25
+ {
26
+ name: 'context_update',
27
+ description: `프로젝트 컨텍스트 업데이트. 작업 종료 시 호출.
28
+ - currentState: 현재 상태 1줄 요약 (필수)
29
+ - recentFiles: 최근 수정 파일 (최대 10개)
30
+ - blockers: 블로커/이슈 (없으면 생략)
31
+ - verification: 마지막 검증 결과 (passed/failed)
32
+ - architectureDecision: 새로운 아키텍처 결정`,
33
+ inputSchema: {
34
+ type: 'object',
35
+ properties: {
36
+ project: { type: 'string', description: '프로젝트명' },
37
+ currentState: { type: 'string', description: '현재 상태 (1줄 요약)' },
38
+ recentFiles: { type: 'array', items: { type: 'string' }, description: '최근 수정 파일' },
39
+ blockers: { type: 'string', description: '블로커/이슈' },
40
+ verification: { type: 'string', enum: ['passed', 'failed'], description: '검증 결과' },
41
+ architectureDecision: { type: 'string', description: '추가할 아키텍처 결정' }
42
+ },
43
+ required: ['project', 'currentState']
44
+ }
45
+ }
46
+ ];
47
+ // ===== 핸들러 =====
48
+ export async function handleContextGet(args) {
49
+ return logger.withTool('context_get', async () => {
50
+ // 입력 검증
51
+ const parsed = ContextGetSchema.safeParse(args);
52
+ if (!parsed.success) {
53
+ return {
54
+ content: [{ type: 'text', text: `Validation error: ${parsed.error.message}` }],
55
+ isError: true
56
+ };
57
+ }
58
+ const { project } = parsed.data;
59
+ // Layer 1: 고정 컨텍스트
60
+ const projectContextStmt = db.prepare('SELECT * FROM project_context WHERE project = ?');
61
+ const projectContext = projectContextStmt.get(project);
62
+ // Layer 2: 활성 컨텍스트
63
+ const activeContextStmt = db.prepare('SELECT * FROM active_context WHERE project = ?');
64
+ const activeContext = activeContextStmt.get(project);
65
+ // Layer 3: 미완료 태스크 (최대 3개)
66
+ const tasksStmt = db.prepare(`
67
+ SELECT id, title, status, priority
68
+ FROM tasks
69
+ WHERE project = ? AND status IN ('pending', 'in_progress')
70
+ ORDER BY priority DESC, created_at DESC
71
+ LIMIT 3
72
+ `);
73
+ const tasks = tasksStmt.all(project);
74
+ // 고정 컨텍스트가 없으면 plan.md에서 자동 추출
75
+ let techStack = {};
76
+ if (!projectContext) {
77
+ const planPath = path.join(APPS_DIR, project, 'plan.md');
78
+ const planContent = await readFileContent(planPath);
79
+ if (planContent) {
80
+ techStack = parseMarkdownTable(planContent, '기술 스택');
81
+ }
82
+ }
83
+ const result = {
84
+ project,
85
+ fixed: {
86
+ techStack: projectContext?.tech_stack ? JSON.parse(projectContext.tech_stack) : techStack,
87
+ architectureDecisions: projectContext?.architecture_decisions ? JSON.parse(projectContext.architecture_decisions) : [],
88
+ codePatterns: projectContext?.code_patterns ? JSON.parse(projectContext.code_patterns) : [],
89
+ specialNotes: projectContext?.special_notes || null
90
+ },
91
+ active: {
92
+ currentState: activeContext?.current_state || 'No active context',
93
+ recentFiles: activeContext?.recent_files ? JSON.parse(activeContext.recent_files) : [],
94
+ blockers: activeContext?.blockers || null,
95
+ lastVerification: activeContext?.last_verification || null,
96
+ updatedAt: activeContext?.updated_at || null
97
+ },
98
+ pendingTasks: tasks.map(t => ({
99
+ id: t.id,
100
+ title: t.title,
101
+ status: t.status,
102
+ priority: t.priority
103
+ }))
104
+ };
105
+ return {
106
+ content: [{
107
+ type: 'text',
108
+ text: JSON.stringify(result, null, 2)
109
+ }]
110
+ };
111
+ }, args);
112
+ }
113
+ export async function handleContextUpdate(args) {
114
+ return logger.withTool('context_update', async () => {
115
+ // 입력 검증
116
+ const parsed = ContextUpdateSchema.safeParse(args);
117
+ if (!parsed.success) {
118
+ return {
119
+ content: [{ type: 'text', text: `Validation error: ${parsed.error.message}` }],
120
+ isError: true
121
+ };
122
+ }
123
+ const { project, currentState, recentFiles, blockers, verification, architectureDecision } = parsed.data;
124
+ // 활성 컨텍스트 업데이트
125
+ const stmt = db.prepare(`
126
+ INSERT OR REPLACE INTO active_context (project, current_state, recent_files, blockers, last_verification, updated_at)
127
+ VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
128
+ `);
129
+ stmt.run(project, currentState, recentFiles ? JSON.stringify(recentFiles.slice(0, 10)) : null, blockers || null, verification || null);
130
+ // 아키텍처 결정 추가 (있으면)
131
+ if (architectureDecision) {
132
+ const getStmt = db.prepare('SELECT architecture_decisions FROM project_context WHERE project = ?');
133
+ const row = getStmt.get(project);
134
+ let decisions = [];
135
+ if (row?.architecture_decisions) {
136
+ try {
137
+ decisions = JSON.parse(row.architecture_decisions);
138
+ }
139
+ catch { /* ignore */ }
140
+ }
141
+ decisions.unshift(architectureDecision);
142
+ decisions = decisions.slice(0, 5);
143
+ const updateStmt = db.prepare(`
144
+ INSERT INTO project_context (project, architecture_decisions, updated_at)
145
+ VALUES (?, ?, CURRENT_TIMESTAMP)
146
+ ON CONFLICT(project) DO UPDATE SET
147
+ architecture_decisions = ?,
148
+ updated_at = CURRENT_TIMESTAMP
149
+ `);
150
+ const decisionsJson = JSON.stringify(decisions);
151
+ updateStmt.run(project, decisionsJson, decisionsJson);
152
+ }
153
+ return {
154
+ content: [{
155
+ type: 'text',
156
+ text: JSON.stringify({
157
+ success: true,
158
+ project,
159
+ updated: {
160
+ currentState,
161
+ recentFiles: recentFiles?.length || 0,
162
+ hasBlockers: !!blockers,
163
+ verification: verification || null,
164
+ architectureDecision: architectureDecision || null
165
+ }
166
+ })
167
+ }]
168
+ };
169
+ }, args);
170
+ }
@@ -0,0 +1,3 @@
1
+ import type { Tool, CallToolResult } from '../types.js';
2
+ export declare const embeddingTools: Tool[];
3
+ export declare function handleRebuildEmbeddings(args: unknown): Promise<CallToolResult>;
@@ -0,0 +1,115 @@
1
+ // 임베딩 도구 (rebuild_embeddings)
2
+ // 시맨틱 검색용 임베딩 관리
3
+ import { db } from '../db/database.js';
4
+ import { generateEmbedding, embeddingToBuffer } from '../utils/embedding.js';
5
+ import { logger } from '../utils/logger.js';
6
+ // ===== 도구 정의 =====
7
+ export const embeddingTools = [
8
+ {
9
+ name: 'rebuild_embeddings',
10
+ description: `임베딩 재생성.
11
+ - force=false: 누락된 임베딩만 생성
12
+ - force=true: 전체 임베딩 재생성
13
+
14
+ 시맨틱 검색 품질 개선에 사용.
15
+ 배치 처리로 메모리 효율적.`,
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {
19
+ force: { type: 'boolean', description: '전체 재생성 (기본: false)' }
20
+ }
21
+ }
22
+ }
23
+ ];
24
+ // ===== 핸들러 =====
25
+ export async function handleRebuildEmbeddings(args) {
26
+ return logger.withTool('rebuild_embeddings', async () => {
27
+ const force = args?.force || false;
28
+ // 대상 메모리 조회
29
+ let sql;
30
+ if (force) {
31
+ sql = 'SELECT id, content FROM memories ORDER BY id';
32
+ }
33
+ else {
34
+ sql = `
35
+ SELECT m.id, m.content FROM memories m
36
+ LEFT JOIN embeddings e ON m.id = e.memory_id
37
+ WHERE e.memory_id IS NULL
38
+ ORDER BY m.id
39
+ `;
40
+ }
41
+ const memories = db.prepare(sql).all();
42
+ if (memories.length === 0) {
43
+ return {
44
+ content: [{
45
+ type: 'text',
46
+ text: JSON.stringify({
47
+ success: true,
48
+ message: 'No embeddings to rebuild',
49
+ processed: 0
50
+ })
51
+ }]
52
+ };
53
+ }
54
+ logger.info('Starting embedding rebuild', {
55
+ total: memories.length,
56
+ force
57
+ }, 'rebuild_embeddings');
58
+ // 배치 처리
59
+ const BATCH_SIZE = 10;
60
+ let processed = 0;
61
+ let failed = 0;
62
+ for (let i = 0; i < memories.length; i += BATCH_SIZE) {
63
+ const batch = memories.slice(i, i + BATCH_SIZE);
64
+ await Promise.all(batch.map(async (memory) => {
65
+ try {
66
+ const embedding = await generateEmbedding(memory.content);
67
+ if (embedding) {
68
+ const stmt = db.prepare(`
69
+ INSERT OR REPLACE INTO embeddings (memory_id, embedding, created_at)
70
+ VALUES (?, ?, CURRENT_TIMESTAMP)
71
+ `);
72
+ stmt.run(memory.id, embeddingToBuffer(embedding));
73
+ processed++;
74
+ }
75
+ else {
76
+ failed++;
77
+ }
78
+ }
79
+ catch (e) {
80
+ failed++;
81
+ logger.error('Embedding generation failed', {
82
+ memoryId: memory.id,
83
+ error: String(e)
84
+ }, 'rebuild_embeddings');
85
+ }
86
+ }));
87
+ // 진행 상황 로깅
88
+ if ((i + BATCH_SIZE) % 50 === 0 || i + BATCH_SIZE >= memories.length) {
89
+ logger.info('Embedding progress', {
90
+ processed,
91
+ failed,
92
+ remaining: memories.length - i - BATCH_SIZE
93
+ }, 'rebuild_embeddings');
94
+ }
95
+ }
96
+ // 최종 통계
97
+ const totalMemories = db.prepare('SELECT COUNT(*) as count FROM memories').get().count;
98
+ const totalEmbeddings = db.prepare('SELECT COUNT(*) as count FROM embeddings').get().count;
99
+ return {
100
+ content: [{
101
+ type: 'text',
102
+ text: JSON.stringify({
103
+ success: true,
104
+ processed,
105
+ failed,
106
+ coverage: `${Math.round((totalEmbeddings / totalMemories) * 100)}%`,
107
+ stats: {
108
+ totalMemories,
109
+ totalEmbeddings
110
+ }
111
+ })
112
+ }]
113
+ };
114
+ }, args);
115
+ }
@@ -0,0 +1,13 @@
1
+ import { handleContextGet, handleContextUpdate } from './context.js';
2
+ import { handleMemoryStore, handleMemorySearch, handleMemoryDelete, handleMemoryStats } from './memory.js';
3
+ import { handleTaskManage } from './task.js';
4
+ import { handleVerify } from './verify.js';
5
+ import { handleLearn, handleRecallSolution } from './learn.js';
6
+ import { handleProjects } from './projects.js';
7
+ import { handleRebuildEmbeddings } from './embedding.js';
8
+ import { handleSessionStart, handleSessionEnd, handleSessionSummary } from './auto-capture.js';
9
+ import type { Tool, CallToolResult } from '../types.js';
10
+ export declare const allToolsV2: Tool[];
11
+ export declare function handleToolV2(name: string, args: unknown): Promise<CallToolResult>;
12
+ export declare const toolNamesV2: string[];
13
+ export { handleContextGet, handleContextUpdate, handleMemoryStore, handleMemorySearch, handleMemoryDelete, handleMemoryStats, handleTaskManage, handleVerify, handleLearn, handleRecallSolution, handleProjects, handleRebuildEmbeddings, handleSessionStart, handleSessionEnd, handleSessionSummary };
@@ -0,0 +1,73 @@
1
+ // 통합 도구 v2 - 15개 도구
2
+ // 기존 46개 도구를 15개로 통합 (자동 컨텍스트 캡처 3개 추가)
3
+ import { contextTools, handleContextGet, handleContextUpdate } from './context.js';
4
+ import { memoryTools, handleMemoryStore, handleMemorySearch, handleMemoryDelete, handleMemoryStats } from './memory.js';
5
+ import { taskTools, handleTaskManage } from './task.js';
6
+ import { verifyTools, handleVerify } from './verify.js';
7
+ import { learnTools, handleLearn, handleRecallSolution } from './learn.js';
8
+ import { projectsTools, handleProjects } from './projects.js';
9
+ import { embeddingTools, handleRebuildEmbeddings } from './embedding.js';
10
+ import { autoCaptureTools, handleSessionStart, handleSessionEnd, handleSessionSummary } from './auto-capture.js';
11
+ // 모든 도구 정의 (15개)
12
+ export const allToolsV2 = [
13
+ ...contextTools, // context_get, context_update
14
+ ...memoryTools, // memory_store, memory_search, memory_delete, memory_stats
15
+ ...taskTools, // task_manage
16
+ ...verifyTools, // verify
17
+ ...learnTools, // learn, recall_solution
18
+ ...projectsTools, // projects
19
+ ...embeddingTools, // rebuild_embeddings
20
+ ...autoCaptureTools // session_start, session_end, session_summary
21
+ ];
22
+ // 도구 핸들러 라우터
23
+ export async function handleToolV2(name, args) {
24
+ switch (name) {
25
+ // Context
26
+ case 'context_get':
27
+ return handleContextGet(args);
28
+ case 'context_update':
29
+ return handleContextUpdate(args);
30
+ // Memory
31
+ case 'memory_store':
32
+ return handleMemoryStore(args);
33
+ case 'memory_search':
34
+ return handleMemorySearch(args);
35
+ case 'memory_delete':
36
+ return handleMemoryDelete(args);
37
+ case 'memory_stats':
38
+ return handleMemoryStats();
39
+ // Task
40
+ case 'task_manage':
41
+ return handleTaskManage(args);
42
+ // Verify
43
+ case 'verify':
44
+ return handleVerify(args);
45
+ // Learn
46
+ case 'learn':
47
+ return handleLearn(args);
48
+ case 'recall_solution':
49
+ return handleRecallSolution(args);
50
+ // Projects
51
+ case 'projects':
52
+ return handleProjects(args);
53
+ // Embedding
54
+ case 'rebuild_embeddings':
55
+ return handleRebuildEmbeddings(args);
56
+ // Auto Capture (Session Lifecycle)
57
+ case 'session_start':
58
+ return handleSessionStart(args);
59
+ case 'session_end':
60
+ return handleSessionEnd(args);
61
+ case 'session_summary':
62
+ return handleSessionSummary(args);
63
+ default:
64
+ return {
65
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
66
+ isError: true
67
+ };
68
+ }
69
+ }
70
+ // 도구 이름 목록
71
+ export const toolNamesV2 = allToolsV2.map(t => t.name);
72
+ // Export individual handlers for testing
73
+ export { handleContextGet, handleContextUpdate, handleMemoryStore, handleMemorySearch, handleMemoryDelete, handleMemoryStats, handleTaskManage, handleVerify, handleLearn, handleRecallSolution, handleProjects, handleRebuildEmbeddings, handleSessionStart, handleSessionEnd, handleSessionSummary };
@@ -0,0 +1,4 @@
1
+ import type { Tool, CallToolResult } from '../types.js';
2
+ export declare const learnTools: Tool[];
3
+ export declare function handleLearn(args: unknown): Promise<CallToolResult>;
4
+ export declare function handleRecallSolution(args: unknown): Promise<CallToolResult>;