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,169 @@
1
+ // Content Filtering 학습/회피 도구 (3개)
2
+ import { db, contentFilterPatterns, loadContentFilterPatterns } from '../db/database.js';
3
+ // ===== 도구 정의 =====
4
+ export const filterTools = [
5
+ {
6
+ name: 'record_filter_pattern',
7
+ description: 'API content filtering에 걸린 패턴을 기록합니다. 비슷한 상황 회피에 사용됩니다.',
8
+ inputSchema: {
9
+ type: 'object',
10
+ properties: {
11
+ patternType: {
12
+ type: 'string',
13
+ enum: ['code_block', 'file_content', 'long_output', 'sensitive_keyword', 'binary_like', 'other'],
14
+ description: '패턴 유형'
15
+ },
16
+ patternDescription: { type: 'string', description: '어떤 상황에서 발생했는지 설명' },
17
+ fileExtension: { type: 'string', description: '관련 파일 확장자 (선택, 예: .kt, .tsx)' },
18
+ exampleContext: { type: 'string', description: '발생 컨텍스트 예시 (민감 정보 제외)' },
19
+ mitigationStrategy: { type: 'string', description: '회피 전략 (예: 청크 분할, 요약만 출력)' }
20
+ },
21
+ required: ['patternType', 'patternDescription']
22
+ }
23
+ },
24
+ {
25
+ name: 'get_filter_patterns',
26
+ description: '기록된 content filtering 패턴 목록을 조회합니다. 응답 생성 시 참고용.',
27
+ inputSchema: {
28
+ type: 'object',
29
+ properties: {
30
+ patternType: { type: 'string', description: '패턴 유형 필터 (선택)' },
31
+ fileExtension: { type: 'string', description: '파일 확장자 필터 (선택)' }
32
+ }
33
+ }
34
+ },
35
+ {
36
+ name: 'get_safe_output_guidelines',
37
+ description: '현재 학습된 패턴 기반으로 안전한 출력 가이드라인을 반환합니다.',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ context: { type: 'string', description: '현재 작업 컨텍스트 (예: kotlin 파일 분석, 긴 코드 출력)' }
42
+ }
43
+ }
44
+ }
45
+ ];
46
+ // ===== 핸들러 =====
47
+ export function recordFilterPattern(patternType, patternDescription, fileExtension, exampleContext, mitigationStrategy) {
48
+ try {
49
+ // 기존 패턴 확인
50
+ const existingStmt = db.prepare(`
51
+ SELECT id, occurrence_count FROM content_filter_patterns
52
+ WHERE pattern_type = ? AND pattern_description = ?
53
+ `);
54
+ const existing = existingStmt.get(patternType, patternDescription);
55
+ if (existing) {
56
+ const updateStmt = db.prepare(`
57
+ UPDATE content_filter_patterns
58
+ SET occurrence_count = ?, last_occurred = CURRENT_TIMESTAMP
59
+ WHERE id = ?
60
+ `);
61
+ updateStmt.run(existing.occurrence_count + 1, existing.id);
62
+ // 캐시 갱신
63
+ loadContentFilterPatterns();
64
+ return {
65
+ content: [{
66
+ type: 'text',
67
+ text: JSON.stringify({
68
+ success: true,
69
+ updated: true,
70
+ id: existing.id,
71
+ occurrenceCount: existing.occurrence_count + 1
72
+ })
73
+ }]
74
+ };
75
+ }
76
+ else {
77
+ const insertStmt = db.prepare(`
78
+ INSERT INTO content_filter_patterns (pattern_type, pattern_description, file_extension, example_context, mitigation_strategy)
79
+ VALUES (?, ?, ?, ?, ?)
80
+ `);
81
+ const result = insertStmt.run(patternType, patternDescription, fileExtension || null, exampleContext || null, mitigationStrategy || null);
82
+ // 캐시 갱신
83
+ loadContentFilterPatterns();
84
+ return {
85
+ content: [{
86
+ type: 'text',
87
+ text: JSON.stringify({
88
+ success: true,
89
+ created: true,
90
+ id: result.lastInsertRowid
91
+ })
92
+ }]
93
+ };
94
+ }
95
+ }
96
+ catch (error) {
97
+ return {
98
+ content: [{ type: 'text', text: `Error: ${error}` }],
99
+ isError: true
100
+ };
101
+ }
102
+ }
103
+ export function getFilterPatterns(patternType, fileExtension) {
104
+ try {
105
+ let filtered = contentFilterPatterns;
106
+ if (patternType) {
107
+ filtered = filtered.filter(p => p.patternType === patternType);
108
+ }
109
+ if (fileExtension) {
110
+ filtered = filtered.filter(p => p.fileExtension === fileExtension);
111
+ }
112
+ return {
113
+ content: [{
114
+ type: 'text',
115
+ text: JSON.stringify({
116
+ found: filtered.length,
117
+ patterns: filtered
118
+ }, null, 2)
119
+ }]
120
+ };
121
+ }
122
+ catch (error) {
123
+ return {
124
+ content: [{ type: 'text', text: `Error: ${error}` }],
125
+ isError: true
126
+ };
127
+ }
128
+ }
129
+ export function getSafeOutputGuidelines(context) {
130
+ try {
131
+ const guidelines = [
132
+ '1. 긴 코드 출력 시 청크로 분할 (500줄 이하)',
133
+ '2. 파일 전체 읽기보다 특정 섹션만 Read (offset, limit 사용)',
134
+ '3. 불완전한 Edit 작업 후 남은 코드 정리',
135
+ '4. 민감할 수 있는 키워드 피하기'
136
+ ];
137
+ // 컨텍스트에 맞는 추가 가이드라인
138
+ if (context) {
139
+ const contextLower = context.toLowerCase();
140
+ if (contextLower.includes('kotlin') || contextLower.includes('.kt')) {
141
+ guidelines.push('5. Kotlin 파일: 긴 클래스는 메서드별로 분석');
142
+ }
143
+ if (contextLower.includes('긴') || contextLower.includes('long')) {
144
+ guidelines.push('5. 긴 출력: 요약 먼저 제공, 상세 내용은 요청 시');
145
+ }
146
+ }
147
+ // 학습된 패턴 기반 추가 가이드라인
148
+ const patternGuidelines = contentFilterPatterns
149
+ .filter(p => p.mitigationStrategy)
150
+ .slice(0, 3)
151
+ .map((p, i) => `${guidelines.length + i + 1}. ${p.mitigationStrategy}`);
152
+ return {
153
+ content: [{
154
+ type: 'text',
155
+ text: JSON.stringify({
156
+ context: context || 'general',
157
+ guidelines: [...guidelines, ...patternGuidelines],
158
+ learnedPatternsCount: contentFilterPatterns.length
159
+ }, null, 2)
160
+ }]
161
+ };
162
+ }
163
+ catch (error) {
164
+ return {
165
+ content: [{ type: 'text', text: `Error: ${error}` }],
166
+ isError: true
167
+ };
168
+ }
169
+ }
@@ -0,0 +1,12 @@
1
+ export * from './project.js';
2
+ export * from './session.js';
3
+ export * from './memory.js';
4
+ export * from './embedding.js';
5
+ export * from './relation.js';
6
+ export * from './feedback.js';
7
+ export * from './filter.js';
8
+ export * from './learning.js';
9
+ export * from './context.js';
10
+ export * from './task.js';
11
+ export * from './solution.js';
12
+ export declare const allTools: import("../types.js").Tool[];
@@ -0,0 +1,38 @@
1
+ // 모든 도구를 내보내는 인덱스 파일
2
+ export * from './project.js';
3
+ export * from './session.js';
4
+ export * from './memory.js';
5
+ export * from './embedding.js';
6
+ export * from './relation.js';
7
+ export * from './feedback.js';
8
+ export * from './filter.js';
9
+ export * from './learning.js';
10
+ export * from './context.js';
11
+ export * from './task.js';
12
+ export * from './solution.js';
13
+ // 도구 정의 배열들
14
+ import { projectTools } from './project.js';
15
+ import { sessionTools } from './session.js';
16
+ import { memoryTools } from './memory.js';
17
+ import { embeddingTools } from './embedding.js';
18
+ import { relationTools } from './relation.js';
19
+ import { feedbackTools } from './feedback.js';
20
+ import { filterTools } from './filter.js';
21
+ import { learningTools } from './learning.js';
22
+ import { contextTools } from './context.js';
23
+ import { taskTools } from './task.js';
24
+ import { solutionTools } from './solution.js';
25
+ // 모든 도구 통합
26
+ export const allTools = [
27
+ ...projectTools,
28
+ ...sessionTools,
29
+ ...memoryTools,
30
+ ...embeddingTools,
31
+ ...relationTools,
32
+ ...feedbackTools,
33
+ ...filterTools,
34
+ ...learningTools,
35
+ ...contextTools,
36
+ ...taskTools,
37
+ ...solutionTools
38
+ ];
@@ -0,0 +1,8 @@
1
+ import type { Tool, CallToolResult, AutoLearnDecisionArgs, AutoLearnFixArgs, AutoLearnPatternArgs, AutoLearnDependencyArgs } from '../types.js';
2
+ export declare const learningTools: Tool[];
3
+ export declare function autoLearnDecision(args: AutoLearnDecisionArgs): Promise<CallToolResult>;
4
+ export declare function autoLearnFix(args: AutoLearnFixArgs): Promise<CallToolResult>;
5
+ export declare function autoLearnPattern(args: AutoLearnPatternArgs): Promise<CallToolResult>;
6
+ export declare function autoLearnDependency(args: AutoLearnDependencyArgs): Promise<CallToolResult>;
7
+ export declare function getProjectKnowledge(project: string, knowledgeType?: string, limit?: number): CallToolResult;
8
+ export declare function getSimilarIssues(errorOrIssue: string, project?: string, limit?: number): Promise<CallToolResult>;
@@ -0,0 +1,395 @@
1
+ // 자동 학습 시스템 도구 (6개)
2
+ import { db } from '../db/database.js';
3
+ import { generateEmbedding, embeddingToBuffer, getEmbeddingPipeline } from '../utils/embedding.js';
4
+ import { semanticSearch } from './embedding.js';
5
+ // ===== 도구 정의 =====
6
+ export const learningTools = [
7
+ {
8
+ name: 'auto_learn_decision',
9
+ description: '아키텍처/기술 결정 사항을 자동 기록합니다. 왜 이 선택을 했는지 기록하여 나중에 참조할 수 있습니다.',
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ project: { type: 'string', description: '프로젝트명' },
14
+ decision: { type: 'string', description: '결정 내용 (예: Socket.IO 대신 WebSocket 사용)' },
15
+ reason: { type: 'string', description: '결정 이유' },
16
+ context: { type: 'string', description: '결정 배경/맥락' },
17
+ alternatives: { type: 'array', items: { type: 'string' }, description: '고려했던 대안들' },
18
+ files: { type: 'array', items: { type: 'string' }, description: '관련 파일들' }
19
+ },
20
+ required: ['project', 'decision', 'reason']
21
+ }
22
+ },
23
+ {
24
+ name: 'auto_learn_fix',
25
+ description: '에러/버그 해결 방법을 자동 기록합니다. 비슷한 에러 발생 시 참조할 수 있습니다.',
26
+ inputSchema: {
27
+ type: 'object',
28
+ properties: {
29
+ project: { type: 'string', description: '프로젝트명' },
30
+ error: { type: 'string', description: '에러 메시지 또는 증상' },
31
+ cause: { type: 'string', description: '원인 (선택)' },
32
+ solution: { type: 'string', description: '해결 방법' },
33
+ files: { type: 'array', items: { type: 'string' }, description: '수정한 파일들' },
34
+ preventionTip: { type: 'string', description: '재발 방지 팁 (선택)' }
35
+ },
36
+ required: ['project', 'error', 'solution']
37
+ }
38
+ },
39
+ {
40
+ name: 'auto_learn_pattern',
41
+ description: '프로젝트의 코드 패턴/컨벤션을 자동 기록합니다. 일관성 유지에 활용됩니다.',
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {
45
+ project: { type: 'string', description: '프로젝트명' },
46
+ patternName: { type: 'string', description: '패턴 이름 (예: Repository 패턴, State hoisting)' },
47
+ description: { type: 'string', description: '패턴 설명' },
48
+ example: { type: 'string', description: '예시 코드나 파일 경로' },
49
+ appliesTo: { type: 'string', description: '적용 대상 (예: 모든 Repository, Compose UI)' }
50
+ },
51
+ required: ['project', 'patternName', 'description']
52
+ }
53
+ },
54
+ {
55
+ name: 'auto_learn_dependency',
56
+ description: '의존성 변경 사항을 자동 기록합니다. 버전 충돌이나 업그레이드 시 참조합니다.',
57
+ inputSchema: {
58
+ type: 'object',
59
+ properties: {
60
+ project: { type: 'string', description: '프로젝트명' },
61
+ dependency: { type: 'string', description: '의존성 이름' },
62
+ action: { type: 'string', enum: ['add', 'remove', 'upgrade', 'downgrade'], description: '작업 유형' },
63
+ fromVersion: { type: 'string', description: '이전 버전 (선택)' },
64
+ toVersion: { type: 'string', description: '새 버전 (선택)' },
65
+ reason: { type: 'string', description: '변경 이유' },
66
+ breakingChanges: { type: 'string', description: 'Breaking changes 내용 (선택)' }
67
+ },
68
+ required: ['project', 'dependency', 'action', 'reason']
69
+ }
70
+ },
71
+ {
72
+ name: 'get_project_knowledge',
73
+ description: '프로젝트에서 학습된 모든 지식을 조회합니다. 결정, 해결, 패턴, 의존성 변경 등.',
74
+ inputSchema: {
75
+ type: 'object',
76
+ properties: {
77
+ project: { type: 'string', description: '프로젝트명' },
78
+ knowledgeType: {
79
+ type: 'string',
80
+ enum: ['all', 'decision', 'fix', 'pattern', 'dependency'],
81
+ description: '지식 유형 필터 (기본: all)'
82
+ },
83
+ limit: { type: 'number', description: '최대 결과 수 (기본: 20)' }
84
+ },
85
+ required: ['project']
86
+ }
87
+ },
88
+ {
89
+ name: 'get_similar_issues',
90
+ description: '비슷한 에러/이슈의 해결 방법을 검색합니다. 시맨틱 검색으로 유사한 문제를 찾습니다.',
91
+ inputSchema: {
92
+ type: 'object',
93
+ properties: {
94
+ errorOrIssue: { type: 'string', description: '에러 메시지 또는 이슈 설명' },
95
+ project: { type: 'string', description: '특정 프로젝트에서만 검색 (선택)' },
96
+ limit: { type: 'number', description: '최대 결과 수 (기본: 5)' }
97
+ },
98
+ required: ['errorOrIssue']
99
+ }
100
+ }
101
+ ];
102
+ // ===== 핸들러 =====
103
+ export async function autoLearnDecision(args) {
104
+ try {
105
+ const content = `[DECISION] ${args.decision}\n이유: ${args.reason}${args.context ? `\n맥락: ${args.context}` : ''}${args.alternatives?.length ? `\n대안들: ${args.alternatives.join(', ')}` : ''}`;
106
+ const stmt = db.prepare(`
107
+ INSERT INTO memories (content, memory_type, tags, project, importance, metadata)
108
+ VALUES (?, 'decision', ?, ?, 7, ?)
109
+ `);
110
+ const tags = JSON.stringify(['auto-learn', 'architecture', 'decision']);
111
+ const metadata = JSON.stringify({
112
+ type: 'decision',
113
+ alternatives: args.alternatives,
114
+ files: args.files
115
+ });
116
+ const result = stmt.run(content, tags, args.project, metadata);
117
+ const memoryId = result.lastInsertRowid;
118
+ // 임베딩 생성
119
+ generateEmbedding(content).then(embedding => {
120
+ if (embedding) {
121
+ const embStmt = db.prepare('INSERT OR REPLACE INTO embeddings (memory_id, embedding) VALUES (?, ?)');
122
+ embStmt.run(memoryId, embeddingToBuffer(embedding));
123
+ }
124
+ });
125
+ return {
126
+ content: [{
127
+ type: 'text',
128
+ text: JSON.stringify({ success: true, id: memoryId, type: 'decision' })
129
+ }]
130
+ };
131
+ }
132
+ catch (error) {
133
+ return {
134
+ content: [{ type: 'text', text: `Error: ${error}` }],
135
+ isError: true
136
+ };
137
+ }
138
+ }
139
+ export async function autoLearnFix(args) {
140
+ try {
141
+ const content = `[FIX] ${args.error}\n해결: ${args.solution}${args.cause ? `\n원인: ${args.cause}` : ''}${args.preventionTip ? `\n예방: ${args.preventionTip}` : ''}`;
142
+ const stmt = db.prepare(`
143
+ INSERT INTO memories (content, memory_type, tags, project, importance, metadata)
144
+ VALUES (?, 'error', ?, ?, 8, ?)
145
+ `);
146
+ const tags = JSON.stringify(['auto-learn', 'fix', 'error-solution']);
147
+ const metadata = JSON.stringify({
148
+ type: 'fix',
149
+ error: args.error,
150
+ solution: args.solution,
151
+ cause: args.cause,
152
+ files: args.files,
153
+ preventionTip: args.preventionTip
154
+ });
155
+ const result = stmt.run(content, tags, args.project, metadata);
156
+ const memoryId = result.lastInsertRowid;
157
+ // 임베딩 생성
158
+ generateEmbedding(content).then(embedding => {
159
+ if (embedding) {
160
+ const embStmt = db.prepare('INSERT OR REPLACE INTO embeddings (memory_id, embedding) VALUES (?, ?)');
161
+ embStmt.run(memoryId, embeddingToBuffer(embedding));
162
+ }
163
+ });
164
+ return {
165
+ content: [{
166
+ type: 'text',
167
+ text: JSON.stringify({ success: true, id: memoryId, type: 'fix' })
168
+ }]
169
+ };
170
+ }
171
+ catch (error) {
172
+ return {
173
+ content: [{ type: 'text', text: `Error: ${error}` }],
174
+ isError: true
175
+ };
176
+ }
177
+ }
178
+ export async function autoLearnPattern(args) {
179
+ try {
180
+ const content = `[PATTERN] ${args.patternName}\n설명: ${args.description}${args.example ? `\n예시: ${args.example}` : ''}${args.appliesTo ? `\n적용대상: ${args.appliesTo}` : ''}`;
181
+ const stmt = db.prepare(`
182
+ INSERT INTO memories (content, memory_type, tags, project, importance, metadata)
183
+ VALUES (?, 'pattern', ?, ?, 6, ?)
184
+ `);
185
+ const tags = JSON.stringify(['auto-learn', 'code-pattern', 'convention']);
186
+ const metadata = JSON.stringify({
187
+ type: 'pattern',
188
+ patternName: args.patternName,
189
+ appliesTo: args.appliesTo
190
+ });
191
+ const result = stmt.run(content, tags, args.project, metadata);
192
+ const memoryId = result.lastInsertRowid;
193
+ // 임베딩 생성
194
+ generateEmbedding(content).then(embedding => {
195
+ if (embedding) {
196
+ const embStmt = db.prepare('INSERT OR REPLACE INTO embeddings (memory_id, embedding) VALUES (?, ?)');
197
+ embStmt.run(memoryId, embeddingToBuffer(embedding));
198
+ }
199
+ });
200
+ return {
201
+ content: [{
202
+ type: 'text',
203
+ text: JSON.stringify({ success: true, id: memoryId, type: 'pattern' })
204
+ }]
205
+ };
206
+ }
207
+ catch (error) {
208
+ return {
209
+ content: [{ type: 'text', text: `Error: ${error}` }],
210
+ isError: true
211
+ };
212
+ }
213
+ }
214
+ export async function autoLearnDependency(args) {
215
+ try {
216
+ const versionInfo = args.fromVersion && args.toVersion
217
+ ? `${args.fromVersion} → ${args.toVersion}`
218
+ : args.toVersion || args.fromVersion || '';
219
+ const content = `[DEPENDENCY] ${args.action.toUpperCase()} ${args.dependency} ${versionInfo}\n이유: ${args.reason}${args.breakingChanges ? `\nBreaking Changes: ${args.breakingChanges}` : ''}`;
220
+ const stmt = db.prepare(`
221
+ INSERT INTO memories (content, memory_type, tags, project, importance, metadata)
222
+ VALUES (?, 'learning', ?, ?, 5, ?)
223
+ `);
224
+ const tags = JSON.stringify(['auto-learn', 'dependency', args.action]);
225
+ const metadata = JSON.stringify({
226
+ type: 'dependency',
227
+ dependency: args.dependency,
228
+ action: args.action,
229
+ fromVersion: args.fromVersion,
230
+ toVersion: args.toVersion,
231
+ breakingChanges: args.breakingChanges
232
+ });
233
+ const result = stmt.run(content, tags, args.project, metadata);
234
+ const memoryId = result.lastInsertRowid;
235
+ // 임베딩 생성
236
+ generateEmbedding(content).then(embedding => {
237
+ if (embedding) {
238
+ const embStmt = db.prepare('INSERT OR REPLACE INTO embeddings (memory_id, embedding) VALUES (?, ?)');
239
+ embStmt.run(memoryId, embeddingToBuffer(embedding));
240
+ }
241
+ });
242
+ return {
243
+ content: [{
244
+ type: 'text',
245
+ text: JSON.stringify({ success: true, id: memoryId, type: 'dependency' })
246
+ }]
247
+ };
248
+ }
249
+ catch (error) {
250
+ return {
251
+ content: [{ type: 'text', text: `Error: ${error}` }],
252
+ isError: true
253
+ };
254
+ }
255
+ }
256
+ export function getProjectKnowledge(project, knowledgeType = 'all', limit = 20) {
257
+ try {
258
+ let sql = `
259
+ SELECT id, content, memory_type, tags, importance, metadata, created_at
260
+ FROM memories
261
+ WHERE project = ?
262
+ AND tags LIKE '%"auto-learn"%'
263
+ `;
264
+ const params = [project];
265
+ if (knowledgeType !== 'all') {
266
+ const typeMap = {
267
+ decision: 'decision',
268
+ fix: 'error',
269
+ pattern: 'pattern',
270
+ dependency: 'learning'
271
+ };
272
+ sql += ` AND memory_type = ?`;
273
+ params.push(typeMap[knowledgeType] || knowledgeType);
274
+ }
275
+ sql += ` ORDER BY importance DESC, created_at DESC LIMIT ?`;
276
+ params.push(limit);
277
+ const stmt = db.prepare(sql);
278
+ const rows = stmt.all(...params);
279
+ const knowledge = rows.map(row => {
280
+ let meta = {};
281
+ try {
282
+ meta = JSON.parse(row.metadata || '{}');
283
+ }
284
+ catch { }
285
+ return {
286
+ id: row.id,
287
+ type: meta.type || row.memory_type,
288
+ content: row.content,
289
+ importance: row.importance,
290
+ createdAt: row.created_at,
291
+ metadata: meta
292
+ };
293
+ });
294
+ // 유형별 통계
295
+ const stats = {
296
+ decision: knowledge.filter(k => k.type === 'decision').length,
297
+ fix: knowledge.filter(k => k.type === 'fix').length,
298
+ pattern: knowledge.filter(k => k.type === 'pattern').length,
299
+ dependency: knowledge.filter(k => k.type === 'dependency').length
300
+ };
301
+ return {
302
+ content: [{
303
+ type: 'text',
304
+ text: JSON.stringify({
305
+ project,
306
+ totalKnowledge: knowledge.length,
307
+ stats,
308
+ knowledge: knowledge.slice(0, limit)
309
+ }, null, 2)
310
+ }]
311
+ };
312
+ }
313
+ catch (error) {
314
+ return {
315
+ content: [{ type: 'text', text: `Error: ${error}` }],
316
+ isError: true
317
+ };
318
+ }
319
+ }
320
+ export async function getSimilarIssues(errorOrIssue, project, limit = 5) {
321
+ try {
322
+ // 먼저 시맨틱 검색 시도
323
+ if (getEmbeddingPipeline()) {
324
+ const result = await semanticSearch(errorOrIssue, limit, 0.3, 'error', project);
325
+ const resultText = JSON.parse(result.content[0].text);
326
+ if (resultText.found > 0) {
327
+ return {
328
+ content: [{
329
+ type: 'text',
330
+ text: JSON.stringify({
331
+ searchType: 'semantic',
332
+ query: errorOrIssue.substring(0, 100),
333
+ found: resultText.found,
334
+ solutions: resultText.results.map((r) => ({
335
+ id: r.id,
336
+ similarity: r.similarity,
337
+ content: r.content,
338
+ project: r.project
339
+ }))
340
+ }, null, 2)
341
+ }]
342
+ };
343
+ }
344
+ }
345
+ // 시맨틱 검색 결과 없으면 FTS 검색
346
+ const keywords = errorOrIssue.split(/\s+/).filter(w => w.length > 3).slice(0, 5);
347
+ const ftsQuery = keywords.join(' OR ');
348
+ let query = `
349
+ SELECT m.id, m.content, m.project, m.metadata
350
+ FROM memories_fts fts
351
+ JOIN memories m ON m.id = fts.rowid
352
+ WHERE memories_fts MATCH ?
353
+ AND m.memory_type = 'error'
354
+ `;
355
+ const params = [ftsQuery];
356
+ if (project) {
357
+ query += ` AND m.project = ?`;
358
+ params.push(project);
359
+ }
360
+ query += ` LIMIT ?`;
361
+ params.push(limit);
362
+ const stmt = db.prepare(query);
363
+ const rows = stmt.all(...params);
364
+ const solutions = rows.map(row => {
365
+ let metadata = {};
366
+ try {
367
+ metadata = JSON.parse(row.metadata || '{}');
368
+ }
369
+ catch { }
370
+ return {
371
+ id: row.id,
372
+ content: row.content,
373
+ project: row.project,
374
+ solution: metadata.solution
375
+ };
376
+ });
377
+ return {
378
+ content: [{
379
+ type: 'text',
380
+ text: JSON.stringify({
381
+ searchType: 'fts',
382
+ query: errorOrIssue.substring(0, 100),
383
+ found: solutions.length,
384
+ solutions
385
+ }, null, 2)
386
+ }]
387
+ };
388
+ }
389
+ catch (error) {
390
+ return {
391
+ content: [{ type: 'text', text: `Error: ${error}` }],
392
+ isError: true
393
+ };
394
+ }
395
+ }
@@ -0,0 +1,8 @@
1
+ import type { Tool, CallToolResult } from '../types.js';
2
+ export declare const memoryTools: Tool[];
3
+ export declare function storeMemory(content: string, memoryType: string, tags?: string[], project?: string, importance?: number, metadata?: Record<string, unknown>): Promise<CallToolResult>;
4
+ export declare function recallMemory(query: string, memoryType?: string, project?: string, limit?: number, minImportance?: number, maxContentLength?: number): CallToolResult;
5
+ export declare function recallByTimeframe(timeframe: string, memoryType?: string, project?: string, limit?: number): CallToolResult;
6
+ export declare function searchByTag(tags: string[], matchAll?: boolean, limit?: number): CallToolResult;
7
+ export declare function getMemoryStats(): CallToolResult;
8
+ export declare function deleteMemory(memoryId: number): CallToolResult;