memento-mcp-server 1.12.0 → 1.13.0-b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/algorithms/forgetting-algorithm.d.ts +21 -13
- package/dist/algorithms/forgetting-algorithm.d.ts.map +1 -1
- package/dist/algorithms/forgetting-algorithm.js +32 -24
- package/dist/algorithms/forgetting-algorithm.js.map +1 -1
- package/dist/algorithms/hybrid-search-engine.d.ts +11 -9
- package/dist/algorithms/hybrid-search-engine.d.ts.map +1 -1
- package/dist/algorithms/hybrid-search-engine.js +77 -75
- package/dist/algorithms/hybrid-search-engine.js.map +1 -1
- package/dist/algorithms/search-engine.d.ts +33 -11
- package/dist/algorithms/search-engine.d.ts.map +1 -1
- package/dist/algorithms/search-engine.js +157 -62
- package/dist/algorithms/search-engine.js.map +1 -1
- package/dist/algorithms/search-ranking.d.ts +57 -50
- package/dist/algorithms/search-ranking.d.ts.map +1 -1
- package/dist/algorithms/search-ranking.js +91 -84
- package/dist/algorithms/search-ranking.js.map +1 -1
- package/dist/algorithms/spaced-repetition.d.ts +18 -13
- package/dist/algorithms/spaced-repetition.d.ts.map +1 -1
- package/dist/algorithms/spaced-repetition.js +28 -23
- package/dist/algorithms/spaced-repetition.js.map +1 -1
- package/dist/algorithms/vector-search-engine-migration.d.ts +8 -6
- package/dist/algorithms/vector-search-engine-migration.d.ts.map +1 -1
- package/dist/algorithms/vector-search-engine-migration.js +13 -11
- package/dist/algorithms/vector-search-engine-migration.js.map +1 -1
- package/dist/algorithms/vector-search-engine-refactored.d.ts +7 -7
- package/dist/algorithms/vector-search-engine-refactored.d.ts.map +1 -1
- package/dist/algorithms/vector-search-engine-refactored.js +7 -7
- package/dist/algorithms/vector-search-engine-refactored.js.map +1 -1
- package/dist/algorithms/vector-search-engine.d.ts +25 -20
- package/dist/algorithms/vector-search-engine.d.ts.map +1 -1
- package/dist/algorithms/vector-search-engine.js +47 -43
- package/dist/algorithms/vector-search-engine.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +4 -1
- package/dist/config/index.js.map +1 -1
- package/dist/database/init.d.ts.map +1 -1
- package/dist/database/init.js +24 -4
- package/dist/database/init.js.map +1 -1
- package/dist/database/migration/migrations/006-fts5-reflection-notes-migration-status.sql +30 -0
- package/dist/database/migration/migrations/006-fts5-reflection-notes.d.ts +113 -0
- package/dist/database/migration/migrations/006-fts5-reflection-notes.d.ts.map +1 -0
- package/dist/database/migration/migrations/006-fts5-reflection-notes.js +441 -0
- package/dist/database/migration/migrations/006-fts5-reflection-notes.js.map +1 -0
- package/dist/database/migration/migrations/006-fts5-reflection-notes.sql +26 -0
- package/dist/database/schema.sql +11 -9
- package/dist/server/bootstrap.d.ts +4 -0
- package/dist/server/bootstrap.d.ts.map +1 -1
- package/dist/server/bootstrap.js +11 -1
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +3 -1
- package/dist/server/context.js.map +1 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +2 -1
- package/dist/server/http-server.js.map +1 -1
- package/dist/server/index.js +3 -1
- package/dist/server/index.js.map +1 -1
- package/dist/services/async-optimizer.d.ts +2 -1
- package/dist/services/async-optimizer.d.ts.map +1 -1
- package/dist/services/async-optimizer.js +28 -1
- package/dist/services/async-optimizer.js.map +1 -1
- package/dist/services/batch-scheduler.d.ts +5 -1
- package/dist/services/batch-scheduler.d.ts.map +1 -1
- package/dist/services/batch-scheduler.js +13 -1
- package/dist/services/batch-scheduler.js.map +1 -1
- package/dist/services/cache-service.js +1 -1
- package/dist/services/cache-service.js.map +1 -1
- package/dist/services/failure-detector.d.ts +120 -0
- package/dist/services/failure-detector.d.ts.map +1 -0
- package/dist/services/failure-detector.js +370 -0
- package/dist/services/failure-detector.js.map +1 -0
- package/dist/services/llm-based-relation-extractor.js +1 -1
- package/dist/services/llm-based-relation-extractor.js.map +1 -1
- package/dist/services/reflexion-worker.d.ts +170 -0
- package/dist/services/reflexion-worker.d.ts.map +1 -0
- package/dist/services/reflexion-worker.js +636 -0
- package/dist/services/reflexion-worker.js.map +1 -0
- package/dist/services/relation-graph.d.ts +2 -2
- package/dist/services/relation-graph.js +3 -3
- package/dist/services/relation-graph.js.map +1 -1
- package/dist/tools/base-tool.d.ts +5 -0
- package/dist/tools/base-tool.d.ts.map +1 -1
- package/dist/tools/base-tool.js +39 -0
- package/dist/tools/base-tool.js.map +1 -1
- package/dist/tools/recall-tool.d.ts.map +1 -1
- package/dist/tools/recall-tool.js +36 -2
- package/dist/tools/recall-tool.js.map +1 -1
- package/dist/tools/remember-tool.d.ts +24 -0
- package/dist/tools/remember-tool.d.ts.map +1 -1
- package/dist/tools/remember-tool.js +445 -273
- package/dist/tools/remember-tool.js.map +1 -1
- package/dist/tools/types.d.ts +5 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/database.d.ts.map +1 -1
- package/dist/utils/database.js +34 -10
- package/dist/utils/database.js.map +1 -1
- package/dist/utils/fts5-migration-status.d.ts +72 -0
- package/dist/utils/fts5-migration-status.d.ts.map +1 -0
- package/dist/utils/fts5-migration-status.js +304 -0
- package/dist/utils/fts5-migration-status.js.map +1 -0
- package/dist/utils/reflection-notes-merge.d.ts +58 -0
- package/dist/utils/reflection-notes-merge.d.ts.map +1 -0
- package/dist/utils/reflection-notes-merge.js +227 -0
- package/dist/utils/reflection-notes-merge.js.map +1 -0
- package/dist/utils/reflection-notes-normalize.d.ts +43 -0
- package/dist/utils/reflection-notes-normalize.d.ts.map +1 -0
- package/dist/utils/reflection-notes-normalize.js +164 -0
- package/dist/utils/reflection-notes-normalize.js.map +1 -0
- package/dist/utils/reflection-notes-schema.d.ts +84 -0
- package/dist/utils/reflection-notes-schema.d.ts.map +1 -0
- package/dist/utils/reflection-notes-schema.js +215 -0
- package/dist/utils/reflection-notes-schema.js.map +1 -0
- package/package.json +3 -1
- package/src/database/schema.sql +11 -9
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflection Notes JSON 정규화 유틸리티
|
|
3
|
+
*
|
|
4
|
+
* reflection_notes 필드를 FTS5 인덱싱을 위해 텍스트로 정규화하는 유틸리티 함수를 제공합니다.
|
|
5
|
+
* 트리거에서 사용되며, JSON 형식(단일 객체 또는 배열)을 FTS5 검색 가능한 텍스트로 변환합니다.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 키 토큰으로 포함할 필드 목록
|
|
9
|
+
* 타입별 검색/필터링을 위해 중요한 키는 토큰으로 포함
|
|
10
|
+
*/
|
|
11
|
+
const KEY_TOKEN_FIELDS = ['failure_type', 'phase'];
|
|
12
|
+
/**
|
|
13
|
+
* 제외할 필드 목록
|
|
14
|
+
* 검색에 불필요한 필드는 토큰화하지 않음
|
|
15
|
+
*/
|
|
16
|
+
const EXCLUDED_FIELDS = ['timestamp'];
|
|
17
|
+
/**
|
|
18
|
+
* 키 토큰 접두사 매핑
|
|
19
|
+
* 키 앞에 접두사를 추가하여 키-값을 구분
|
|
20
|
+
*/
|
|
21
|
+
const KEY_TOKEN_PREFIXES = {
|
|
22
|
+
failure_type: 'type',
|
|
23
|
+
phase: 'phase'
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* 단일 Reflection Note 객체를 텍스트로 정규화
|
|
27
|
+
*
|
|
28
|
+
* 정규화 규칙:
|
|
29
|
+
* - 키 토큰 포함: failure_type, phase는 "key:value" 형식으로 포함
|
|
30
|
+
* - 값 필드 토큰화: 모든 값 필드를 추출하여 공백으로 구분
|
|
31
|
+
* - 제외 필드: timestamp는 제외
|
|
32
|
+
*
|
|
33
|
+
* @param note - 정규화할 Reflection Note 객체
|
|
34
|
+
* @returns 정규화된 텍스트 문자열
|
|
35
|
+
*/
|
|
36
|
+
function normalizeReflectionNoteObject(note) {
|
|
37
|
+
if (!note || typeof note !== 'object') {
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
const tokens = [];
|
|
41
|
+
// 키 토큰 포함 (failure_type, phase)
|
|
42
|
+
for (const key of KEY_TOKEN_FIELDS) {
|
|
43
|
+
if (note[key] !== undefined && note[key] !== null) {
|
|
44
|
+
const prefix = KEY_TOKEN_PREFIXES[key] || key;
|
|
45
|
+
const value = String(note[key]).trim();
|
|
46
|
+
if (value.length > 0) {
|
|
47
|
+
tokens.push(`${prefix}:${value}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// 값 필드 토큰화 (모든 값 필드 추출)
|
|
52
|
+
for (const [key, value] of Object.entries(note)) {
|
|
53
|
+
// 키 토큰 필드와 제외 필드는 이미 처리했거나 제외
|
|
54
|
+
if (KEY_TOKEN_FIELDS.includes(key) || EXCLUDED_FIELDS.includes(key)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// 값이 문자열인 경우 토큰화
|
|
58
|
+
if (typeof value === 'string' && value.trim().length > 0) {
|
|
59
|
+
tokens.push(value.trim());
|
|
60
|
+
}
|
|
61
|
+
// 값이 숫자나 불린인 경우 문자열로 변환
|
|
62
|
+
else if (typeof value === 'number' || typeof value === 'boolean') {
|
|
63
|
+
tokens.push(String(value));
|
|
64
|
+
}
|
|
65
|
+
// 값이 객체나 배열인 경우 재귀적으로 처리하지 않음 (현재 스키마에서는 단순 값만 사용)
|
|
66
|
+
}
|
|
67
|
+
return tokens.join(' ');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* reflection_notes JSON을 FTS5 인덱싱을 위해 텍스트로 정규화
|
|
71
|
+
*
|
|
72
|
+
* 정규화 규칙:
|
|
73
|
+
* - 단일 객체: 모든 값 필드를 추출하여 공백으로 구분된 단일 문자열로 병합
|
|
74
|
+
* - 배열: 각 요소의 모든 값 필드를 추출하여 공백으로 구분된 단일 문자열로 병합
|
|
75
|
+
* - 키 토큰 포함: failure_type, phase는 "key:value" 형식으로 포함
|
|
76
|
+
* - 제외 필드: timestamp는 제외
|
|
77
|
+
*
|
|
78
|
+
* 예시:
|
|
79
|
+
* - `{"failure_type": "tool_error", "failure_description": "API timeout"}`
|
|
80
|
+
* → "type:tool_error API timeout"
|
|
81
|
+
* - `[{"failure_description": "API timeout"}, {"lessons_learned": "retry needed"}]`
|
|
82
|
+
* → "API timeout retry needed"
|
|
83
|
+
*
|
|
84
|
+
* @param reflectionNotes - 정규화할 reflection_notes (JSON 문자열, 객체, 또는 배열)
|
|
85
|
+
* @returns 정규화된 텍스트 문자열 (FTS5 인덱싱용)
|
|
86
|
+
*/
|
|
87
|
+
export function normalizeReflectionNotes(reflectionNotes) {
|
|
88
|
+
// NULL 또는 빈 값 처리
|
|
89
|
+
if (!reflectionNotes || reflectionNotes === '') {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
// 문자열인 경우 JSON 파싱
|
|
93
|
+
let parsed;
|
|
94
|
+
if (typeof reflectionNotes === 'string') {
|
|
95
|
+
try {
|
|
96
|
+
parsed = JSON.parse(reflectionNotes);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
// JSON 파싱 실패 시 빈 문자열 반환
|
|
100
|
+
return '';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
parsed = reflectionNotes;
|
|
105
|
+
}
|
|
106
|
+
// 배열인 경우: 각 요소를 정규화하여 병합
|
|
107
|
+
if (Array.isArray(parsed)) {
|
|
108
|
+
const normalizedItems = parsed
|
|
109
|
+
.map(item => normalizeReflectionNoteObject(item))
|
|
110
|
+
.filter(text => text.length > 0);
|
|
111
|
+
return normalizedItems.join(' ');
|
|
112
|
+
}
|
|
113
|
+
// 단일 객체인 경우: 정규화
|
|
114
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
115
|
+
return normalizeReflectionNoteObject(parsed);
|
|
116
|
+
}
|
|
117
|
+
// 예상치 못한 타입인 경우 빈 문자열 반환
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 정규화된 텍스트에서 키 토큰 추출 (검색 쿼리 빌더용)
|
|
122
|
+
*
|
|
123
|
+
* @param normalizedText - 정규화된 텍스트
|
|
124
|
+
* @returns 키 토큰 배열 (예: ["type:tool_error", "phase:manual"])
|
|
125
|
+
*/
|
|
126
|
+
export function extractKeyTokens(normalizedText) {
|
|
127
|
+
const tokens = [];
|
|
128
|
+
const keyTokenPattern = /(type|phase):\w+/g;
|
|
129
|
+
let match;
|
|
130
|
+
while ((match = keyTokenPattern.exec(normalizedText)) !== null) {
|
|
131
|
+
tokens.push(match[0]);
|
|
132
|
+
}
|
|
133
|
+
return tokens;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 검색 쿼리 예시 생성 (문서화용)
|
|
137
|
+
*
|
|
138
|
+
* @returns 검색 쿼리 예시 객체
|
|
139
|
+
*/
|
|
140
|
+
export function getSearchQueryExamples() {
|
|
141
|
+
return [
|
|
142
|
+
{
|
|
143
|
+
description: 'tool_error 타입만 검색',
|
|
144
|
+
query: 'type:tool_error',
|
|
145
|
+
explanation: 'failure_type이 tool_error인 reflection_notes만 검색'
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
description: '특정 키워드 검색',
|
|
149
|
+
query: 'API timeout',
|
|
150
|
+
explanation: 'failure_description, lessons_learned 등에서 "API timeout" 검색'
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
description: '타입과 키워드 조합 검색',
|
|
154
|
+
query: 'type:tool_error API',
|
|
155
|
+
explanation: 'tool_error 타입이면서 "API"를 포함하는 reflection_notes 검색'
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
description: 'phase 필터링',
|
|
159
|
+
query: 'phase:auto',
|
|
160
|
+
explanation: 'phase가 auto인 reflection_notes만 검색'
|
|
161
|
+
}
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=reflection-notes-normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflection-notes-normalize.js","sourceRoot":"","sources":["../../src/utils/reflection-notes-normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflection Notes JSON 스키마 검증 유틸리티
|
|
3
|
+
*
|
|
4
|
+
* reflection_notes 필드의 JSON 스키마를 검증하는 유틸리티 함수를 제공합니다.
|
|
5
|
+
* 단일 객체 또는 배열 형식 모두 지원합니다.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/**
|
|
9
|
+
* Reflection Note 스키마 정의
|
|
10
|
+
*
|
|
11
|
+
* 필수 필드:
|
|
12
|
+
* - failure_type: 실패 유형 (tool_error | user_feedback | metric_failure)
|
|
13
|
+
* - failure_description: 실패에 대한 상세 설명 (최대 5000자)
|
|
14
|
+
* - timestamp: Reflexion 기록 시각 (ISO 8601 형식)
|
|
15
|
+
*
|
|
16
|
+
* 옵션 필드:
|
|
17
|
+
* - original_task: 원래 수행하려던 작업 (최대 2000자)
|
|
18
|
+
* - lessons_learned: 학습한 교훈 (최대 5000자)
|
|
19
|
+
* - suggested_improvements: 제안하는 개선 방안 (최대 5000자)
|
|
20
|
+
* - phase: 기록 방식 (manual | auto, 기본값: manual)
|
|
21
|
+
*/
|
|
22
|
+
export declare const ReflectionNoteSchema: z.ZodObject<{
|
|
23
|
+
failure_type: z.ZodEnum<["tool_error", "user_feedback", "metric_failure"]>;
|
|
24
|
+
failure_description: z.ZodString;
|
|
25
|
+
timestamp: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
26
|
+
original_task: z.ZodOptional<z.ZodString>;
|
|
27
|
+
lessons_learned: z.ZodOptional<z.ZodString>;
|
|
28
|
+
suggested_improvements: z.ZodOptional<z.ZodString>;
|
|
29
|
+
phase: z.ZodDefault<z.ZodEnum<["manual", "auto"]>>;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
failure_type: "tool_error" | "user_feedback" | "metric_failure";
|
|
32
|
+
phase: "auto" | "manual";
|
|
33
|
+
timestamp: string;
|
|
34
|
+
failure_description: string;
|
|
35
|
+
original_task?: string | undefined;
|
|
36
|
+
lessons_learned?: string | undefined;
|
|
37
|
+
suggested_improvements?: string | undefined;
|
|
38
|
+
}, {
|
|
39
|
+
failure_type: "tool_error" | "user_feedback" | "metric_failure";
|
|
40
|
+
timestamp: string;
|
|
41
|
+
failure_description: string;
|
|
42
|
+
phase?: "auto" | "manual" | undefined;
|
|
43
|
+
original_task?: string | undefined;
|
|
44
|
+
lessons_learned?: string | undefined;
|
|
45
|
+
suggested_improvements?: string | undefined;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Reflection Note 타입 정의
|
|
49
|
+
*/
|
|
50
|
+
export type ReflectionNote = z.infer<typeof ReflectionNoteSchema>;
|
|
51
|
+
/**
|
|
52
|
+
* 검증 결과 타입
|
|
53
|
+
*/
|
|
54
|
+
export interface ValidationResult {
|
|
55
|
+
isValid: boolean;
|
|
56
|
+
errors?: Array<{
|
|
57
|
+
field: string;
|
|
58
|
+
expected: string;
|
|
59
|
+
actual: any;
|
|
60
|
+
message: string;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 단일 Reflection Note 객체 검증
|
|
65
|
+
*
|
|
66
|
+
* @param data - 검증할 객체
|
|
67
|
+
* @returns 검증 결과
|
|
68
|
+
*/
|
|
69
|
+
export declare function validateReflectionNote(data: unknown): ValidationResult;
|
|
70
|
+
/**
|
|
71
|
+
* 단일 객체 또는 배열 형식 모두 지원하는 검증 함수
|
|
72
|
+
*
|
|
73
|
+
* @param jsonString - 검증할 JSON 문자열
|
|
74
|
+
* @returns 검증 결과
|
|
75
|
+
*/
|
|
76
|
+
export declare function validateReflectionNotes(jsonString: string): ValidationResult;
|
|
77
|
+
/**
|
|
78
|
+
* 검증 결과를 사람이 읽기 쉬운 에러 메시지로 변환
|
|
79
|
+
*
|
|
80
|
+
* @param result - 검증 결과
|
|
81
|
+
* @returns 에러 메시지 문자열
|
|
82
|
+
*/
|
|
83
|
+
export declare function formatValidationErrors(result: ValidationResult): string;
|
|
84
|
+
//# sourceMappingURL=reflection-notes-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflection-notes-schema.d.ts","sourceRoot":"","sources":["../../src/utils/reflection-notes-schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;EAmD/B,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,GAAG,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CA+BtE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAoF5E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAavE"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflection Notes JSON 스키마 검증 유틸리티
|
|
3
|
+
*
|
|
4
|
+
* reflection_notes 필드의 JSON 스키마를 검증하는 유틸리티 함수를 제공합니다.
|
|
5
|
+
* 단일 객체 또는 배열 형식 모두 지원합니다.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/**
|
|
9
|
+
* ISO 8601 형식의 날짜 문자열 검증
|
|
10
|
+
* 예: "2025-01-01T00:00:00Z", "2025-01-01T00:00:00.000Z"
|
|
11
|
+
*/
|
|
12
|
+
const iso8601Regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/;
|
|
13
|
+
/**
|
|
14
|
+
* Reflection Note 스키마 정의
|
|
15
|
+
*
|
|
16
|
+
* 필수 필드:
|
|
17
|
+
* - failure_type: 실패 유형 (tool_error | user_feedback | metric_failure)
|
|
18
|
+
* - failure_description: 실패에 대한 상세 설명 (최대 5000자)
|
|
19
|
+
* - timestamp: Reflexion 기록 시각 (ISO 8601 형식)
|
|
20
|
+
*
|
|
21
|
+
* 옵션 필드:
|
|
22
|
+
* - original_task: 원래 수행하려던 작업 (최대 2000자)
|
|
23
|
+
* - lessons_learned: 학습한 교훈 (최대 5000자)
|
|
24
|
+
* - suggested_improvements: 제안하는 개선 방안 (최대 5000자)
|
|
25
|
+
* - phase: 기록 방식 (manual | auto, 기본값: manual)
|
|
26
|
+
*/
|
|
27
|
+
export const ReflectionNoteSchema = z.object({
|
|
28
|
+
failure_type: z.enum(['tool_error', 'user_feedback', 'metric_failure'], {
|
|
29
|
+
errorMap: (issue, ctx) => {
|
|
30
|
+
if (issue.code === z.ZodIssueCode.invalid_enum_value) {
|
|
31
|
+
return {
|
|
32
|
+
message: `failure_type는 'tool_error', 'user_feedback', 'metric_failure' 중 하나여야 합니다. 현재 값: ${ctx.data}`
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return { message: ctx.defaultError };
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
failure_description: z.string()
|
|
39
|
+
.min(1, 'failure_description은 비어있을 수 없습니다')
|
|
40
|
+
.max(5000, 'failure_description은 최대 5000자를 초과할 수 없습니다'),
|
|
41
|
+
timestamp: z.string()
|
|
42
|
+
.min(1, 'timestamp는 필수입니다')
|
|
43
|
+
.refine((val) => iso8601Regex.test(val), {
|
|
44
|
+
message: 'timestamp는 ISO 8601 형식이어야 합니다 (예: 2025-01-01T00:00:00Z)'
|
|
45
|
+
})
|
|
46
|
+
.refine((val) => {
|
|
47
|
+
// 실제로 유효한 날짜인지 확인
|
|
48
|
+
const date = new Date(val);
|
|
49
|
+
return !isNaN(date.getTime());
|
|
50
|
+
}, {
|
|
51
|
+
message: 'timestamp는 유효한 날짜여야 합니다'
|
|
52
|
+
}),
|
|
53
|
+
original_task: z.string()
|
|
54
|
+
.max(2000, 'original_task는 최대 2000자를 초과할 수 없습니다')
|
|
55
|
+
.optional(),
|
|
56
|
+
lessons_learned: z.string()
|
|
57
|
+
.max(5000, 'lessons_learned는 최대 5000자를 초과할 수 없습니다')
|
|
58
|
+
.optional(),
|
|
59
|
+
suggested_improvements: z.string()
|
|
60
|
+
.max(5000, 'suggested_improvements는 최대 5000자를 초과할 수 없습니다')
|
|
61
|
+
.optional(),
|
|
62
|
+
phase: z.enum(['manual', 'auto'], {
|
|
63
|
+
errorMap: (issue, ctx) => {
|
|
64
|
+
if (issue.code === z.ZodIssueCode.invalid_enum_value) {
|
|
65
|
+
return {
|
|
66
|
+
message: `phase는 'manual' 또는 'auto'여야 합니다. 현재 값: ${ctx.data}`
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return { message: ctx.defaultError };
|
|
70
|
+
}
|
|
71
|
+
}).default('manual')
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* 단일 Reflection Note 객체 검증
|
|
75
|
+
*
|
|
76
|
+
* @param data - 검증할 객체
|
|
77
|
+
* @returns 검증 결과
|
|
78
|
+
*/
|
|
79
|
+
export function validateReflectionNote(data) {
|
|
80
|
+
try {
|
|
81
|
+
ReflectionNoteSchema.parse(data);
|
|
82
|
+
return { isValid: true };
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof z.ZodError) {
|
|
86
|
+
const errors = error.errors.map((err) => {
|
|
87
|
+
const path = err.path.join('.');
|
|
88
|
+
return {
|
|
89
|
+
field: path || 'root',
|
|
90
|
+
expected: err.code === z.ZodIssueCode.invalid_enum_value
|
|
91
|
+
? `enum 값 중 하나 (${err.options?.join(', ')})`
|
|
92
|
+
: err.code === z.ZodIssueCode.invalid_type
|
|
93
|
+
? err.expected
|
|
94
|
+
: '유효한 값',
|
|
95
|
+
actual: err.path.length > 0 ? err.path.reduce((obj, key) => obj?.[key], data) : data,
|
|
96
|
+
message: err.message
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
return { isValid: false, errors };
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
isValid: false,
|
|
103
|
+
errors: [{
|
|
104
|
+
field: 'root',
|
|
105
|
+
expected: '유효한 Reflection Note 객체',
|
|
106
|
+
actual: data,
|
|
107
|
+
message: error instanceof Error ? error.message : String(error)
|
|
108
|
+
}]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 단일 객체 또는 배열 형식 모두 지원하는 검증 함수
|
|
114
|
+
*
|
|
115
|
+
* @param jsonString - 검증할 JSON 문자열
|
|
116
|
+
* @returns 검증 결과
|
|
117
|
+
*/
|
|
118
|
+
export function validateReflectionNotes(jsonString) {
|
|
119
|
+
if (!jsonString || jsonString.trim() === '') {
|
|
120
|
+
return {
|
|
121
|
+
isValid: false,
|
|
122
|
+
errors: [{
|
|
123
|
+
field: 'root',
|
|
124
|
+
expected: '비어있지 않은 JSON 문자열',
|
|
125
|
+
actual: jsonString,
|
|
126
|
+
message: 'reflection_notes는 빈 문자열일 수 없습니다'
|
|
127
|
+
}]
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
let parsed;
|
|
131
|
+
try {
|
|
132
|
+
parsed = JSON.parse(jsonString);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return {
|
|
136
|
+
isValid: false,
|
|
137
|
+
errors: [{
|
|
138
|
+
field: 'root',
|
|
139
|
+
expected: '유효한 JSON 형식',
|
|
140
|
+
actual: jsonString,
|
|
141
|
+
message: `JSON 파싱 실패: ${error instanceof Error ? error.message : String(error)}`
|
|
142
|
+
}]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// 배열인 경우
|
|
146
|
+
if (Array.isArray(parsed)) {
|
|
147
|
+
if (parsed.length === 0) {
|
|
148
|
+
return {
|
|
149
|
+
isValid: false,
|
|
150
|
+
errors: [{
|
|
151
|
+
field: 'root',
|
|
152
|
+
expected: '최소 1개 이상의 요소를 포함한 배열',
|
|
153
|
+
actual: parsed,
|
|
154
|
+
message: 'reflection_notes 배열은 최소 1개 이상의 요소를 포함해야 합니다'
|
|
155
|
+
}]
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// 배열의 각 요소 검증
|
|
159
|
+
const allErrors = [];
|
|
160
|
+
parsed.forEach((item, index) => {
|
|
161
|
+
const result = validateReflectionNote(item);
|
|
162
|
+
if (!result.isValid && result.errors) {
|
|
163
|
+
// 인덱스를 필드 경로에 추가
|
|
164
|
+
result.errors.forEach((err) => {
|
|
165
|
+
allErrors.push({
|
|
166
|
+
field: `[${index}].${err.field}`,
|
|
167
|
+
expected: err.expected,
|
|
168
|
+
actual: err.actual,
|
|
169
|
+
message: err.message
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
if (allErrors.length > 0) {
|
|
175
|
+
return {
|
|
176
|
+
isValid: false,
|
|
177
|
+
errors: allErrors
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return { isValid: true };
|
|
181
|
+
}
|
|
182
|
+
// 단일 객체인 경우
|
|
183
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
184
|
+
return validateReflectionNote(parsed);
|
|
185
|
+
}
|
|
186
|
+
// 객체나 배열이 아닌 경우
|
|
187
|
+
return {
|
|
188
|
+
isValid: false,
|
|
189
|
+
errors: [{
|
|
190
|
+
field: 'root',
|
|
191
|
+
expected: 'JSON 객체 또는 배열',
|
|
192
|
+
actual: typeof parsed,
|
|
193
|
+
message: `reflection_notes는 JSON 객체 또는 배열이어야 합니다. 현재 타입: ${typeof parsed}`
|
|
194
|
+
}]
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 검증 결과를 사람이 읽기 쉬운 에러 메시지로 변환
|
|
199
|
+
*
|
|
200
|
+
* @param result - 검증 결과
|
|
201
|
+
* @returns 에러 메시지 문자열
|
|
202
|
+
*/
|
|
203
|
+
export function formatValidationErrors(result) {
|
|
204
|
+
if (result.isValid || !result.errors) {
|
|
205
|
+
return '';
|
|
206
|
+
}
|
|
207
|
+
const messages = result.errors.map((err) => {
|
|
208
|
+
const actualStr = typeof err.actual === 'object'
|
|
209
|
+
? JSON.stringify(err.actual).substring(0, 100)
|
|
210
|
+
: String(err.actual).substring(0, 100);
|
|
211
|
+
return `필드 '${err.field}': ${err.message} (기대값: ${err.expected}, 실제값: ${actualStr})`;
|
|
212
|
+
});
|
|
213
|
+
return messages.join('\n');
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=reflection-notes-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflection-notes-schema.js","sourceRoot":"","sources":["../../src/utils/reflection-notes-schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memento-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0-b",
|
|
4
4
|
"description": "AI Agent 기억 보조 MCP 서버 - 사람의 기억 구조를 모사한 스토리지+검색+요약+망각 메커니즘",
|
|
5
5
|
"main": "dist/server/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
"start:http-v2": "node dist/server/http-server-v2.js",
|
|
22
22
|
"test": "vitest",
|
|
23
23
|
"test:ci": "vitest --run --reporter=basic",
|
|
24
|
+
"test:vector-search-quality": "vitest --run src/test/test-vector-search-quality-with-consolidation.spec.ts",
|
|
25
|
+
"test:vector-search-quality:ci": "vitest --run --reporter=junit --reporter=json --outputFile.junit=./test-results/vector-search-quality-junit.xml --outputFile.json=./test-results/vector-search-quality-results.json src/test/test-vector-search-quality-with-consolidation.spec.ts",
|
|
24
26
|
"lint": "eslint src/**/*.ts",
|
|
25
27
|
"type-check": "tsc --noEmit",
|
|
26
28
|
"db:init": "tsx src/database/init.ts",
|
package/src/database/schema.sql
CHANGED
|
@@ -98,26 +98,28 @@ CREATE VIRTUAL TABLE IF NOT EXISTS memory_item_fts USING fts5(
|
|
|
98
98
|
content,
|
|
99
99
|
tags,
|
|
100
100
|
source,
|
|
101
|
+
reflection_notes,
|
|
101
102
|
content='memory_item',
|
|
102
103
|
content_rowid='rowid'
|
|
103
104
|
);
|
|
104
105
|
|
|
105
|
-
-- FTS5 트리거 (자동
|
|
106
|
+
-- FTS5 트리거 (자동 동기화, reflection_notes 정규화 포함)
|
|
107
|
+
-- Note: normalize_reflection_notes 함수는 데이터베이스 초기화 시 등록되어야 함
|
|
106
108
|
CREATE TRIGGER IF NOT EXISTS memory_item_fts_insert AFTER INSERT ON memory_item BEGIN
|
|
107
|
-
INSERT INTO memory_item_fts(rowid, content, tags, source)
|
|
108
|
-
VALUES (new.rowid, new.content, new.tags, new.source);
|
|
109
|
+
INSERT INTO memory_item_fts(rowid, content, tags, source, reflection_notes)
|
|
110
|
+
VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
|
|
109
111
|
END;
|
|
110
112
|
|
|
111
113
|
CREATE TRIGGER IF NOT EXISTS memory_item_fts_delete AFTER DELETE ON memory_item BEGIN
|
|
112
|
-
INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source)
|
|
113
|
-
VALUES('delete', old.rowid, old.content, old.tags, old.source);
|
|
114
|
+
INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source, reflection_notes)
|
|
115
|
+
VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
|
|
114
116
|
END;
|
|
115
117
|
|
|
116
118
|
CREATE TRIGGER IF NOT EXISTS memory_item_fts_update AFTER UPDATE ON memory_item BEGIN
|
|
117
|
-
INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source)
|
|
118
|
-
VALUES('delete', old.rowid, old.content, old.tags, old.source);
|
|
119
|
-
INSERT INTO memory_item_fts(rowid, content, tags, source)
|
|
120
|
-
VALUES (new.rowid, new.content, new.tags, new.source);
|
|
119
|
+
INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source, reflection_notes)
|
|
120
|
+
VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
|
|
121
|
+
INSERT INTO memory_item_fts(rowid, content, tags, source, reflection_notes)
|
|
122
|
+
VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
|
|
121
123
|
END;
|
|
122
124
|
|
|
123
125
|
-- 임베딩 저장 테이블 (다중 제공자/차원 지원)
|