memento-mcp-server 1.15.0 → 1.16.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.
Files changed (61) hide show
  1. package/dist/domains/relation/tools/visualize-relations-tool.d.ts +2 -2
  2. package/dist/infrastructure/database/database/migration/migrations/009-quality-assurance-schema.d.ts +60 -0
  3. package/dist/infrastructure/database/database/migration/migrations/009-quality-assurance-schema.d.ts.map +1 -0
  4. package/dist/infrastructure/database/database/migration/migrations/009-quality-assurance-schema.js +276 -0
  5. package/dist/infrastructure/database/database/migration/migrations/009-quality-assurance-schema.js.map +1 -0
  6. package/dist/infrastructure/database/database/migration/migrations/009-quality-assurance-schema.sql +128 -0
  7. package/dist/infrastructure/scheduler/batch-scheduler.d.ts +17 -0
  8. package/dist/infrastructure/scheduler/batch-scheduler.d.ts.map +1 -1
  9. package/dist/infrastructure/scheduler/batch-scheduler.js +130 -0
  10. package/dist/infrastructure/scheduler/batch-scheduler.js.map +1 -1
  11. package/dist/infrastructure/scheduler/jobs/quality-measurement-batch-job.d.ts +108 -0
  12. package/dist/infrastructure/scheduler/jobs/quality-measurement-batch-job.d.ts.map +1 -0
  13. package/dist/infrastructure/scheduler/jobs/quality-measurement-batch-job.js +184 -0
  14. package/dist/infrastructure/scheduler/jobs/quality-measurement-batch-job.js.map +1 -0
  15. package/dist/server/http-server.d.ts.map +1 -1
  16. package/dist/server/http-server.js +3 -0
  17. package/dist/server/http-server.js.map +1 -1
  18. package/dist/server/routes/quality.routes.d.ts +14 -0
  19. package/dist/server/routes/quality.routes.d.ts.map +1 -0
  20. package/dist/server/routes/quality.routes.js +460 -0
  21. package/dist/server/routes/quality.routes.js.map +1 -0
  22. package/dist/services/quality-assurance/quality-assurance-service.d.ts +207 -0
  23. package/dist/services/quality-assurance/quality-assurance-service.d.ts.map +1 -0
  24. package/dist/services/quality-assurance/quality-assurance-service.js +247 -0
  25. package/dist/services/quality-assurance/quality-assurance-service.js.map +1 -0
  26. package/dist/services/quality-assurance/quality-evaluator.d.ts +163 -0
  27. package/dist/services/quality-assurance/quality-evaluator.d.ts.map +1 -0
  28. package/dist/services/quality-assurance/quality-evaluator.js +256 -0
  29. package/dist/services/quality-assurance/quality-evaluator.js.map +1 -0
  30. package/dist/services/quality-assurance/quality-metrics-collector.d.ts +221 -0
  31. package/dist/services/quality-assurance/quality-metrics-collector.d.ts.map +1 -0
  32. package/dist/services/quality-assurance/quality-metrics-collector.js +796 -0
  33. package/dist/services/quality-assurance/quality-metrics-collector.js.map +1 -0
  34. package/dist/services/quality-assurance/quality-recorder.d.ts +108 -0
  35. package/dist/services/quality-assurance/quality-recorder.d.ts.map +1 -0
  36. package/dist/services/quality-assurance/quality-recorder.js +281 -0
  37. package/dist/services/quality-assurance/quality-recorder.js.map +1 -0
  38. package/dist/services/quality-assurance/quality-reporter.d.ts +189 -0
  39. package/dist/services/quality-assurance/quality-reporter.d.ts.map +1 -0
  40. package/dist/services/quality-assurance/quality-reporter.js +558 -0
  41. package/dist/services/quality-assurance/quality-reporter.js.map +1 -0
  42. package/dist/services/quality-assurance/quality-threshold-manager.d.ts +102 -0
  43. package/dist/services/quality-assurance/quality-threshold-manager.d.ts.map +1 -0
  44. package/dist/services/quality-assurance/quality-threshold-manager.js +252 -0
  45. package/dist/services/quality-assurance/quality-threshold-manager.js.map +1 -0
  46. package/dist/shared/utils/database.d.ts +7 -0
  47. package/dist/shared/utils/database.d.ts.map +1 -1
  48. package/dist/shared/utils/database.js +24 -0
  49. package/dist/shared/utils/database.js.map +1 -1
  50. package/dist/test/helpers/search-quality-metrics.d.ts +96 -0
  51. package/dist/test/helpers/search-quality-metrics.d.ts.map +1 -0
  52. package/dist/test/helpers/search-quality-metrics.js +185 -0
  53. package/dist/test/helpers/search-quality-metrics.js.map +1 -0
  54. package/dist/test/helpers/vector-search-quality-metrics.d.ts +1287 -0
  55. package/dist/test/helpers/vector-search-quality-metrics.d.ts.map +1 -0
  56. package/dist/test/helpers/vector-search-quality-metrics.js +2214 -0
  57. package/dist/test/helpers/vector-search-quality-metrics.js.map +1 -0
  58. package/package.json +5 -1
  59. package/scripts/generate-ground-truth.ts +353 -0
  60. package/scripts/quality-report.ts +166 -0
  61. package/scripts/quality-thresholds.ts +279 -0
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 품질 리포트 생성 CLI 스크립트
4
+ *
5
+ * 사용법:
6
+ * npm run quality:report
7
+ * npm run quality:report -- --format json
8
+ * npm run quality:report -- --namespace search
9
+ * npm run quality:report -- --from 2024-01-01T00:00:00Z --to 2024-12-31T23:59:59Z
10
+ * npm run quality:report -- --output report.md
11
+ * npm run quality:report -- --format html --output report.html
12
+ *
13
+ * 예제:
14
+ * npm run quality:report
15
+ * npm run quality:report -- --format json
16
+ * npm run quality:report -- --namespace search --format markdown
17
+ * npm run quality:report -- --from 2024-01-01T00:00:00Z --to 2024-12-31T23:59:59Z --output report.md
18
+ * npm run quality:report -- --format html --output report.html --context ci
19
+ */
20
+
21
+ import { writeFileSync, mkdirSync, existsSync } from 'fs';
22
+ import { join } from 'path';
23
+ import Database from 'better-sqlite3';
24
+ import { QualityAssuranceService } from '../src/services/quality-assurance/quality-assurance-service.js';
25
+ import { initializeDatabase } from '../src/infrastructure/database/database/init.js';
26
+ import type { ReportFormat, ReportOptions } from '../src/services/quality-assurance/quality-reporter.js';
27
+
28
+ /**
29
+ * CLI 옵션
30
+ */
31
+ interface CliOptions {
32
+ format?: ReportFormat;
33
+ namespace?: string;
34
+ context?: string;
35
+ from?: string;
36
+ to?: string;
37
+ output?: string;
38
+ }
39
+
40
+ /**
41
+ * 명령줄 인자 파싱
42
+ */
43
+ function parseArgs(): CliOptions {
44
+ const args = process.argv.slice(2);
45
+ const options: CliOptions = {};
46
+
47
+ for (let i = 0; i < args.length; i++) {
48
+ const arg = args[i];
49
+ if (arg === '--format' && args[i + 1]) {
50
+ const format = args[i + 1] as ReportFormat;
51
+ if (['markdown', 'json', 'html'].includes(format)) {
52
+ options.format = format;
53
+ }
54
+ i++;
55
+ } else if (arg === '--namespace' && args[i + 1]) {
56
+ options.namespace = args[i + 1];
57
+ i++;
58
+ } else if (arg === '--context' && args[i + 1]) {
59
+ options.context = args[i + 1];
60
+ i++;
61
+ } else if (arg === '--from' && args[i + 1]) {
62
+ options.from = args[i + 1];
63
+ i++;
64
+ } else if (arg === '--to' && args[i + 1]) {
65
+ options.to = args[i + 1];
66
+ i++;
67
+ } else if (arg === '--output' && args[i + 1]) {
68
+ options.output = args[i + 1];
69
+ i++;
70
+ } else if (arg === '--help' || arg === '-h') {
71
+ printHelp();
72
+ process.exit(0);
73
+ }
74
+ }
75
+
76
+ return options;
77
+ }
78
+
79
+ /**
80
+ * 도움말 출력
81
+ */
82
+ function printHelp(): void {
83
+ console.log(`
84
+ 품질 리포트 생성 CLI
85
+
86
+ 사용법:
87
+ npm run quality:report [options]
88
+
89
+ 옵션:
90
+ --format <format> 리포트 형식 (markdown, json, html, 기본값: markdown)
91
+ --namespace <namespace> 네임스페이스 필터 (예: search, relation, consolidation, storage)
92
+ --context <context> 컨텍스트 필터 (기본값: default)
93
+ --from <iso8601> 시작 시간 (ISO 8601 형식, 예: 2024-01-01T00:00:00Z)
94
+ --to <iso8601> 종료 시간 (ISO 8601 형식, 예: 2024-12-31T23:59:59Z)
95
+ --output <file> 출력 파일 경로 (지정하지 않으면 콘솔에 출력)
96
+ --help, -h 도움말 출력
97
+
98
+ 예제:
99
+ npm run quality:report
100
+ npm run quality:report -- --format json
101
+ npm run quality:report -- --namespace search --format markdown
102
+ npm run quality:report -- --from 2024-01-01T00:00:00Z --to 2024-12-31T23:59:59Z --output report.md
103
+ npm run quality:report -- --format html --output report.html --context ci
104
+ `);
105
+ }
106
+
107
+ /**
108
+ * 메인 함수
109
+ */
110
+ async function main(): Promise<void> {
111
+ const options = parseArgs();
112
+
113
+ try {
114
+ // 데이터베이스 초기화
115
+ const db = await initializeDatabase();
116
+ const qualityService = new QualityAssuranceService(db);
117
+
118
+ // 리포트 옵션 구성
119
+ const reportOptions: ReportOptions = {
120
+ format: options.format || 'markdown',
121
+ namespace: options.namespace,
122
+ context: options.context || 'default',
123
+ from: options.from,
124
+ to: options.to
125
+ };
126
+
127
+ // 리포트 생성
128
+ console.log('📊 품질 리포트 생성 중...');
129
+ const report = await qualityService.generateReport(reportOptions);
130
+
131
+ // 출력 처리
132
+ if (options.output) {
133
+ // 파일로 저장
134
+ const outputPath = join(process.cwd(), options.output);
135
+ const outputDir = join(outputPath, '..');
136
+
137
+ // 디렉토리가 없으면 생성
138
+ if (!existsSync(outputDir)) {
139
+ mkdirSync(outputDir, { recursive: true });
140
+ }
141
+
142
+ writeFileSync(outputPath, report, 'utf-8');
143
+ console.log(`✅ 리포트가 저장되었습니다: ${outputPath}`);
144
+ } else {
145
+ // 콘솔에 출력
146
+ console.log('\n' + report);
147
+ }
148
+
149
+ db.close();
150
+ } catch (error) {
151
+ console.error('❌ 오류 발생:', error instanceof Error ? error.message : String(error));
152
+ if (error instanceof Error && error.stack) {
153
+ console.error(error.stack);
154
+ }
155
+ process.exit(1);
156
+ }
157
+ }
158
+
159
+ // 스크립트 직접 실행 시
160
+ if (import.meta.url === `file://${process.argv[1]}` || import.meta.url.endsWith(process.argv[1])) {
161
+ main().catch(error => {
162
+ console.error('❌ 치명적 오류:', error);
163
+ process.exit(1);
164
+ });
165
+ }
166
+
@@ -0,0 +1,279 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 품질 임계값 관리 CLI 스크립트
4
+ *
5
+ * 사용법:
6
+ * npm run quality:thresholds list [--namespace <namespace>] [--context <context>]
7
+ * npm run quality:thresholds set <namespace> <key> <value> <type> [--context <context>] [--description <description>]
8
+ * npm run quality:thresholds delete <namespace> <key> [--context <context>]
9
+ * npm run quality:thresholds init [--context <context>] [--overwrite]
10
+ * npm run quality:thresholds get <namespace> <key> [--context <context>]
11
+ *
12
+ * 예제:
13
+ * npm run quality:thresholds list
14
+ * npm run quality:thresholds list --namespace search
15
+ * npm run quality:thresholds set search precision_at_5 0.75 min --context default --description "Updated threshold"
16
+ * npm run quality:thresholds delete search precision_at_5 --context default
17
+ * npm run quality:thresholds init
18
+ * npm run quality:thresholds init --overwrite
19
+ * npm run quality:thresholds get search precision_at_5
20
+ */
21
+
22
+ import Database from 'better-sqlite3';
23
+ import { join } from 'path';
24
+ import { QualityThresholdManager } from '../src/services/quality-assurance/quality-threshold-manager.js';
25
+ import { initializeDatabase } from '../src/infrastructure/database/database/init.js';
26
+
27
+ /**
28
+ * CLI 옵션
29
+ */
30
+ interface CliOptions {
31
+ namespace?: string;
32
+ key?: string;
33
+ value?: number;
34
+ type?: 'min' | 'max';
35
+ context?: string;
36
+ description?: string;
37
+ overwrite?: boolean;
38
+ }
39
+
40
+ /**
41
+ * 명령줄 인자 파싱
42
+ */
43
+ function parseArgs(): { command: string; options: CliOptions } {
44
+ const args = process.argv.slice(2);
45
+ const command = args[0] || 'help';
46
+ const options: CliOptions = {};
47
+
48
+ for (let i = 1; i < args.length; i++) {
49
+ const arg = args[i];
50
+ if (arg === '--namespace' && args[i + 1]) {
51
+ options.namespace = args[i + 1];
52
+ i++;
53
+ } else if (arg === '--context' && args[i + 1]) {
54
+ options.context = args[i + 1];
55
+ i++;
56
+ } else if (arg === '--description' && args[i + 1]) {
57
+ options.description = args[i + 1];
58
+ i++;
59
+ } else if (arg === '--overwrite') {
60
+ options.overwrite = true;
61
+ } else if (arg === '--value' && args[i + 1]) {
62
+ options.value = parseFloat(args[i + 1]);
63
+ i++;
64
+ } else if (arg === '--type' && args[i + 1]) {
65
+ const type = args[i + 1] as 'min' | 'max';
66
+ if (['min', 'max'].includes(type)) {
67
+ options.type = type;
68
+ }
69
+ i++;
70
+ } else if (!options.namespace && !arg.startsWith('--')) {
71
+ options.namespace = arg;
72
+ } else if (!options.key && !arg.startsWith('--') && options.namespace) {
73
+ options.key = arg;
74
+ } else if (!options.value && !arg.startsWith('--') && options.key && !isNaN(parseFloat(arg))) {
75
+ options.value = parseFloat(arg);
76
+ } else if (!options.type && !arg.startsWith('--') && options.value && ['min', 'max'].includes(arg)) {
77
+ options.type = arg as 'min' | 'max';
78
+ }
79
+ }
80
+
81
+ return { command, options };
82
+ }
83
+
84
+ /**
85
+ * 도움말 출력
86
+ */
87
+ function printHelp(): void {
88
+ console.log(`
89
+ 품질 임계값 관리 CLI
90
+
91
+ 사용법:
92
+ npm run quality:thresholds <command> [options]
93
+
94
+ 명령어:
95
+ list 모든 임계값 조회
96
+ get <namespace> <key> 특정 임계값 조회
97
+ set <namespace> <key> <value> <type> 임계값 설정
98
+ delete <namespace> <key> 임계값 삭제
99
+ init 기본 임계값 초기화
100
+ help 도움말 출력
101
+
102
+ 옵션:
103
+ --namespace <namespace> 네임스페이스 필터 (예: search, relation, consolidation, storage)
104
+ --context <context> 컨텍스트 (기본값: default)
105
+ --description <text> 설명 (set 명령어에서만 사용)
106
+ --overwrite 기존 임계값 덮어쓰기 (init 명령어에서만 사용)
107
+ --value <number> 임계값 (set 명령어에서 사용, 위치 인자로도 가능)
108
+ --type <min|max> 임계값 타입 (set 명령어에서 사용, 위치 인자로도 가능)
109
+
110
+ 예제:
111
+ npm run quality:thresholds list
112
+ npm run quality:thresholds list --namespace search
113
+ npm run quality:thresholds get search precision_at_5
114
+ npm run quality:thresholds set search precision_at_5 0.75 min
115
+ npm run quality:thresholds set search precision_at_5 0.75 min --context ci --description "CI threshold"
116
+ npm run quality:thresholds delete search precision_at_5
117
+ npm run quality:thresholds init
118
+ npm run quality:thresholds init --overwrite
119
+ `);
120
+ }
121
+
122
+ /**
123
+ * 임계값 목록 출력
124
+ */
125
+ function printThresholds(thresholds: any[], options: CliOptions): void {
126
+ if (thresholds.length === 0) {
127
+ console.log('임계값이 설정되지 않았습니다.');
128
+ return;
129
+ }
130
+
131
+ console.log(`\n총 ${thresholds.length}개의 임계값:\n`);
132
+ console.log('Namespace | Key | Value | Type | Context | Description');
133
+ console.log('----------|-----|-------|------|---------|------------');
134
+
135
+ for (const threshold of thresholds) {
136
+ const namespace = threshold.metric_namespace.padEnd(9);
137
+ const key = threshold.metric_key.padEnd(20);
138
+ const value = threshold.threshold_value.toFixed(3).padStart(5);
139
+ const type = threshold.threshold_type.padEnd(4);
140
+ const context = (threshold.context || 'default').padEnd(7);
141
+ const description = threshold.description || '-';
142
+
143
+ console.log(`${namespace} | ${key} | ${value} | ${type} | ${context} | ${description}`);
144
+ }
145
+ console.log('');
146
+ }
147
+
148
+ /**
149
+ * 메인 함수
150
+ */
151
+ async function main(): Promise<void> {
152
+ const { command, options } = parseArgs();
153
+
154
+ if (command === 'help' || command === '--help' || command === '-h') {
155
+ printHelp();
156
+ process.exit(0);
157
+ }
158
+
159
+ try {
160
+ // 데이터베이스 초기화
161
+ const db = await initializeDatabase();
162
+ const thresholdManager = new QualityThresholdManager(db);
163
+
164
+ const context = options.context || 'default';
165
+
166
+ switch (command) {
167
+ case 'list': {
168
+ const thresholds = thresholdManager.getAllThresholds(options.namespace, context);
169
+ printThresholds(thresholds, options);
170
+ break;
171
+ }
172
+
173
+ case 'get': {
174
+ if (!options.namespace || !options.key) {
175
+ console.error('❌ 오류: namespace와 key를 지정해야 합니다.');
176
+ console.error('사용법: npm run quality:thresholds get <namespace> <key> [--context <context>]');
177
+ process.exit(1);
178
+ }
179
+
180
+ const threshold = thresholdManager.getThreshold(options.namespace, options.key, context);
181
+ if (!threshold) {
182
+ console.log(`임계값이 설정되지 않았습니다: ${options.namespace}.${options.key} (${context})`);
183
+ } else {
184
+ console.log('\n임계값 정보:');
185
+ console.log(` Namespace: ${threshold.metric_namespace}`);
186
+ console.log(` Key: ${threshold.metric_key}`);
187
+ console.log(` Value: ${threshold.threshold_value}`);
188
+ console.log(` Type: ${threshold.threshold_type}`);
189
+ console.log(` Context: ${threshold.context}`);
190
+ console.log(` Description: ${threshold.description || '-'}`);
191
+ console.log(` Updated: ${threshold.updated_at}`);
192
+ console.log('');
193
+ }
194
+ break;
195
+ }
196
+
197
+ case 'set': {
198
+ if (!options.namespace || !options.key || options.value === undefined || !options.type) {
199
+ console.error('❌ 오류: namespace, key, value, type을 모두 지정해야 합니다.');
200
+ console.error('사용법: npm run quality:thresholds set <namespace> <key> <value> <type> [--context <context>] [--description <description>]');
201
+ process.exit(1);
202
+ }
203
+
204
+ if (options.value < 0 || options.value > 1) {
205
+ console.error('❌ 오류: 임계값은 0과 1 사이의 값이어야 합니다.');
206
+ process.exit(1);
207
+ }
208
+
209
+ const threshold = thresholdManager.setThreshold(
210
+ options.namespace,
211
+ options.key,
212
+ {
213
+ threshold_value: options.value,
214
+ threshold_type: options.type,
215
+ description: options.description
216
+ },
217
+ context
218
+ );
219
+
220
+ console.log(`✅ 임계값 설정 완료: ${threshold.metric_namespace}.${threshold.metric_key} (${threshold.context})`);
221
+ console.log(` Value: ${threshold.threshold_value}`);
222
+ console.log(` Type: ${threshold.threshold_type}`);
223
+ if (threshold.description) {
224
+ console.log(` Description: ${threshold.description}`);
225
+ }
226
+ break;
227
+ }
228
+
229
+ case 'delete': {
230
+ if (!options.namespace || !options.key) {
231
+ console.error('❌ 오류: namespace와 key를 지정해야 합니다.');
232
+ console.error('사용법: npm run quality:thresholds delete <namespace> <key> [--context <context>]');
233
+ process.exit(1);
234
+ }
235
+
236
+ const deleted = thresholdManager.deleteThreshold(options.namespace, options.key, context);
237
+ if (deleted) {
238
+ console.log(`✅ 임계값 삭제 완료: ${options.namespace}.${options.key} (${context})`);
239
+ } else {
240
+ console.log(`⚠️ 임계값이 존재하지 않습니다: ${options.namespace}.${options.key} (${context})`);
241
+ }
242
+ break;
243
+ }
244
+
245
+ case 'init': {
246
+ const count = thresholdManager.initializeDefaultThresholds(context, options.overwrite || false);
247
+ console.log(`✅ 기본 임계값 초기화 완료: ${count}개 (context: ${context})`);
248
+ if (options.overwrite) {
249
+ console.log(' 기존 임계값을 덮어썼습니다.');
250
+ } else {
251
+ console.log(' 기존 임계값은 유지되었습니다.');
252
+ }
253
+ break;
254
+ }
255
+
256
+ default:
257
+ console.error(`❌ 알 수 없는 명령어: ${command}`);
258
+ printHelp();
259
+ process.exit(1);
260
+ }
261
+
262
+ db.close();
263
+ } catch (error) {
264
+ console.error('❌ 오류 발생:', error instanceof Error ? error.message : String(error));
265
+ if (error instanceof Error && error.stack) {
266
+ console.error(error.stack);
267
+ }
268
+ process.exit(1);
269
+ }
270
+ }
271
+
272
+ // 스크립트 직접 실행 시
273
+ if (import.meta.url === `file://${process.argv[1]}` || import.meta.url.endsWith(process.argv[1])) {
274
+ main().catch(error => {
275
+ console.error('❌ 치명적 오류:', error);
276
+ process.exit(1);
277
+ });
278
+ }
279
+