@axboot-mcp/mcp-server 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.
- package/CLAUDE.md +119 -0
- package/MCP_TOOL_PLAN.md +710 -0
- package/MCP_USAGE.md +914 -0
- package/README.md +168 -0
- package/REPOSITORY_CONVENTIONS.md +250 -0
- package/SEARCH_PARAMS_MCP_TOOL_COMPLETE_PLAN.md +646 -0
- package/SEARCH_PARAMS_PLAN.md +2570 -0
- package/STORE_PATTERNS.md +1178 -0
- package/debug-dto.js +72 -0
- package/generate-banner-store.js +62 -0
- package/generation-plan.json +2176 -0
- package/generation-results.json +1817 -0
- package/package.json +45 -0
- package/scripts/batch-generate-all.js +159 -0
- package/scripts/batch-generate-mcp.js +329 -0
- package/scripts/batch-generate-stores-v2.js +272 -0
- package/scripts/batch-generate-stores.js +179 -0
- package/scripts/batch-plan.json +3810 -0
- package/scripts/batch-process.py +90 -0
- package/scripts/batch-regenerate.js +356 -0
- package/scripts/direct-generate.js +227 -0
- package/scripts/execute-batches.js +1911 -0
- package/scripts/generate-all-stores.js +144 -0
- package/scripts/generate-stores-mcp.js +161 -0
- package/scripts/generate-stores-v2.js +450 -0
- package/scripts/generate-stores-v3.js +412 -0
- package/scripts/generate-stores-v4.js +521 -0
- package/scripts/generate-stores.js +382 -0
- package/scripts/repos-to-process.json +1899 -0
- package/src/config/nh-layout-patterns.ts +166 -0
- package/src/docs/HOOK_GENERATION_PLAN.md +2226 -0
- package/src/docs/NH_STORE_PATTERNS.md +297 -0
- package/src/docs/README.md +216 -0
- package/src/docs/index.ts +28 -0
- package/src/docs/loader.ts +568 -0
- package/src/docs/patterns.json +419 -0
- package/src/docs/practical-examples.md +732 -0
- package/src/docs/quick-start.md +257 -0
- package/src/docs/requirements-analysis-guide.md +364 -0
- package/src/docs/rules.json +321 -0
- package/src/docs/store-pattern-analysis.md +664 -0
- package/src/docs/store-patterns-rules.md +1168 -0
- package/src/docs/store-patterns-usage-guide.md +1835 -0
- package/src/docs/troubleshooting.md +544 -0
- package/src/docs/type-selection-guide.md +572 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/AntD-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +1515 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/DataGrid-/354/202/254/354/232/251/353/262/225.md +866 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/FormItem-/354/202/254/354/232/251/353/262/225.md +903 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/FormModal-/354/202/254/354/232/251/353/262/225.md +1155 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/MCP-/353/260/224/354/235/264/353/270/214/354/275/224/353/224/251-/352/260/200/354/235/264/353/223/234.md +1133 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/MSW-Mock-/353/215/260/354/235/264/355/204/260-/354/202/254/354/232/251/353/262/225.md +579 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/Search-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +738 -0
- package/src/docs//354/202/254/354/232/251/353/262/225/Store-/355/214/250/355/204/264-/354/202/254/354/232/251/353/262/225.md +1135 -0
- package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/352/265/254/354/204/261-/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234/354/210/234/354/204/234.md +1805 -0
- package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234-/355/224/204/353/241/254/355/224/204/355/212/270-/352/260/200/354/235/264/353/223/234.md +946 -0
- package/src/docs//354/202/254/354/232/251/353/262/225//355/231/225/354/236/245/355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/354/203/201/354/204/270-/355/224/204/353/241/254/355/224/204/355/212/270/352/260/200/354/235/264/353/223/234.md +2422 -0
- package/src/features/store-features.ts +232 -0
- package/src/handlers/analyze-requirements.ts +403 -0
- package/src/handlers/analyze.ts +1373 -0
- package/src/handlers/generate-from-requirements.ts +250 -0
- package/src/handlers/generate-hook.ts +950 -0
- package/src/handlers/generate-interactive.ts +840 -0
- package/src/handlers/generate-listdatagrid.ts +521 -0
- package/src/handlers/generate-multi-stores.ts +577 -0
- package/src/handlers/generate-requirements-from-layout.ts +160 -0
- package/src/handlers/generate-search-params.ts +717 -0
- package/src/handlers/generate.ts +911 -0
- package/src/handlers/list-templates.ts +104 -0
- package/src/handlers/scan-metadata.ts +485 -0
- package/src/handlers/suggest-layout.ts +326 -0
- package/src/index.ts +959 -0
- package/src/prompts/search-params.md +793 -0
- package/src/templates/index.ts +107 -0
- package/src/templates/unified.ts +462 -0
- package/store-generation-error-patterns.md +225 -0
- package/test/useAgentStore.ts +136 -0
- package/test-server.js +78 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
// 현재 파일 위치 기준으로 docs 폴더 경로 계산
|
|
5
|
+
// 빌드 후 dist/docs 폴더를 참조
|
|
6
|
+
// loader.js 자체가 dist/docs에 있으므로 현재 디렉토리를 반환
|
|
7
|
+
function getDocsDir(): string {
|
|
8
|
+
// 현재 모듈의 경로를 동적으로 계산
|
|
9
|
+
const callerPath = new Error().stack?.split('\n')[2]?.match(/\((.*?):\d+:\d+\)/)?.[1];
|
|
10
|
+
if (callerPath) {
|
|
11
|
+
const callerDir = path.dirname(callerPath);
|
|
12
|
+
// loader.js가 dist/docs에 있으므로 현재 디렉토리를 반환
|
|
13
|
+
return callerDir;
|
|
14
|
+
}
|
|
15
|
+
// fallback: 현재 작업 디렉토리 기준
|
|
16
|
+
return path.join(process.cwd(), 'dist', 'docs');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DOCS_DIR = getDocsDir();
|
|
20
|
+
|
|
21
|
+
export interface DocsContent {
|
|
22
|
+
patterns: string;
|
|
23
|
+
rules: string;
|
|
24
|
+
usageGuide: string;
|
|
25
|
+
quickStart: string;
|
|
26
|
+
requirementsAnalysis: string;
|
|
27
|
+
practicalExamples: string;
|
|
28
|
+
troubleshooting: string;
|
|
29
|
+
typeSelection: string;
|
|
30
|
+
readme: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface LoadedDocs {
|
|
34
|
+
patternsJson: any;
|
|
35
|
+
rulesJson: any;
|
|
36
|
+
markdown: DocsContent;
|
|
37
|
+
fullContext: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Load all documentation for store generation
|
|
42
|
+
*/
|
|
43
|
+
export function loadDocs(): LoadedDocs {
|
|
44
|
+
const docsDir = DOCS_DIR;
|
|
45
|
+
|
|
46
|
+
// Load JSON files
|
|
47
|
+
const patternsJson = JSON.parse(
|
|
48
|
+
fs.readFileSync(path.join(docsDir, 'patterns.json'), 'utf-8')
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const rulesJson = JSON.parse(
|
|
52
|
+
fs.readFileSync(path.join(docsDir, 'rules.json'), 'utf-8')
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// Load markdown files
|
|
56
|
+
const patterns = fs.readFileSync(
|
|
57
|
+
path.join(docsDir, 'store-pattern-analysis.md'),
|
|
58
|
+
'utf-8'
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const rules = fs.readFileSync(
|
|
62
|
+
path.join(docsDir, 'store-patterns-rules.md'),
|
|
63
|
+
'utf-8'
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const usageGuide = fs.readFileSync(
|
|
67
|
+
path.join(docsDir, 'store-patterns-usage-guide.md'),
|
|
68
|
+
'utf-8'
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const quickStart = fs.readFileSync(
|
|
72
|
+
path.join(docsDir, 'quick-start.md'),
|
|
73
|
+
'utf-8'
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const requirementsAnalysis = fs.readFileSync(
|
|
77
|
+
path.join(docsDir, 'requirements-analysis-guide.md'),
|
|
78
|
+
'utf-8'
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const practicalExamples = fs.readFileSync(
|
|
82
|
+
path.join(docsDir, 'practical-examples.md'),
|
|
83
|
+
'utf-8'
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const troubleshooting = fs.readFileSync(
|
|
87
|
+
path.join(docsDir, 'troubleshooting.md'),
|
|
88
|
+
'utf-8'
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const typeSelection = fs.readFileSync(
|
|
92
|
+
path.join(docsDir, 'type-selection-guide.md'),
|
|
93
|
+
'utf-8'
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const readme = fs.readFileSync(
|
|
97
|
+
path.join(docsDir, 'README.md'),
|
|
98
|
+
'utf-8'
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Build full context for LLM
|
|
102
|
+
const fullContext = buildFullContext({
|
|
103
|
+
patterns,
|
|
104
|
+
rules,
|
|
105
|
+
usageGuide,
|
|
106
|
+
quickStart,
|
|
107
|
+
requirementsAnalysis,
|
|
108
|
+
practicalExamples,
|
|
109
|
+
troubleshooting,
|
|
110
|
+
typeSelection,
|
|
111
|
+
readme
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
patternsJson,
|
|
116
|
+
rulesJson,
|
|
117
|
+
markdown: {
|
|
118
|
+
patterns,
|
|
119
|
+
rules,
|
|
120
|
+
usageGuide,
|
|
121
|
+
quickStart,
|
|
122
|
+
requirementsAnalysis,
|
|
123
|
+
practicalExamples,
|
|
124
|
+
troubleshooting,
|
|
125
|
+
typeSelection,
|
|
126
|
+
readme
|
|
127
|
+
},
|
|
128
|
+
fullContext
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get store type information from patterns.json
|
|
134
|
+
*/
|
|
135
|
+
export function getStoreTypeInfo(type: number): any {
|
|
136
|
+
const docs = loadDocs();
|
|
137
|
+
const typeKey = type.toString();
|
|
138
|
+
return docs.patternsJson.storeTypes[typeKey] || null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get field combinations for store generation
|
|
143
|
+
*/
|
|
144
|
+
export function getFieldCombinations(): any {
|
|
145
|
+
const docs = loadDocs();
|
|
146
|
+
return docs.patternsJson.fieldCombinations;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get initial values for createStates
|
|
151
|
+
*/
|
|
152
|
+
export function getInitialValues(type?: number): any {
|
|
153
|
+
const docs = loadDocs();
|
|
154
|
+
const common = docs.patternsJson.initialValues.common;
|
|
155
|
+
const typeSpecific = type
|
|
156
|
+
? docs.patternsJson.initialValues.typeSpecific[`type${type}`] || {}
|
|
157
|
+
: {};
|
|
158
|
+
return { ...common, ...typeSpecific };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Build full documentation context for LLM prompt injection
|
|
163
|
+
*/
|
|
164
|
+
function buildFullContext(markdown: DocsContent): string {
|
|
165
|
+
return `
|
|
166
|
+
# NH-FE-B Store Pattern Documentation
|
|
167
|
+
|
|
168
|
+
## 1. Pattern Analysis
|
|
169
|
+
${markdown.patterns}
|
|
170
|
+
|
|
171
|
+
## 2. Rules and Constraints
|
|
172
|
+
${markdown.rules}
|
|
173
|
+
|
|
174
|
+
## 3. Usage Guide
|
|
175
|
+
${markdown.usageGuide}
|
|
176
|
+
|
|
177
|
+
## 4. Quick Start Guide
|
|
178
|
+
${markdown.quickStart}
|
|
179
|
+
|
|
180
|
+
## 5. Requirements Analysis Guide
|
|
181
|
+
${markdown.requirementsAnalysis}
|
|
182
|
+
|
|
183
|
+
## 6. Practical Examples
|
|
184
|
+
${markdown.practicalExamples}
|
|
185
|
+
|
|
186
|
+
## 7. Troubleshooting
|
|
187
|
+
${markdown.troubleshooting}
|
|
188
|
+
|
|
189
|
+
## 8. Type Selection Guide
|
|
190
|
+
${markdown.typeSelection}
|
|
191
|
+
|
|
192
|
+
## 9. Documentation Index
|
|
193
|
+
${markdown.readme}
|
|
194
|
+
`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Get metadata fields for a specific store type
|
|
199
|
+
*/
|
|
200
|
+
export function getMetadataFields(type: number): {
|
|
201
|
+
required: string[];
|
|
202
|
+
optional: string[];
|
|
203
|
+
} {
|
|
204
|
+
const typeInfo = getStoreTypeInfo(type);
|
|
205
|
+
if (!typeInfo) {
|
|
206
|
+
return { required: [], optional: [] };
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
required: typeInfo.metadata.required || [],
|
|
210
|
+
optional: typeInfo.metadata.optional || []
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get states fields for a specific store type
|
|
216
|
+
*/
|
|
217
|
+
export function getStatesFields(type: number): {
|
|
218
|
+
required: string[];
|
|
219
|
+
optional: string[];
|
|
220
|
+
} {
|
|
221
|
+
const typeInfo = getStoreTypeInfo(type);
|
|
222
|
+
if (!typeInfo) {
|
|
223
|
+
return { required: [], optional: [] };
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
required: typeInfo.states.required || [],
|
|
227
|
+
optional: typeInfo.states.optional || []
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get actions for a specific store type
|
|
233
|
+
*/
|
|
234
|
+
export function getActions(type: number): {
|
|
235
|
+
required: string[];
|
|
236
|
+
optional: string[];
|
|
237
|
+
} {
|
|
238
|
+
const typeInfo = getStoreTypeInfo(type);
|
|
239
|
+
if (!typeInfo) {
|
|
240
|
+
return { required: [], optional: [] };
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
required: typeInfo.actions.required || [],
|
|
244
|
+
optional: typeInfo.actions.optional || []
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Get store type fields (metadata, states, actions, subscribe)
|
|
250
|
+
*/
|
|
251
|
+
export function getStoreTypeFields(type: number): {
|
|
252
|
+
metadata: { required: string[]; optional: string[] };
|
|
253
|
+
states: { required: string[]; optional: string[] };
|
|
254
|
+
actions: { required: string[]; optional: string[] };
|
|
255
|
+
subscribeSelector: string[];
|
|
256
|
+
} {
|
|
257
|
+
const typeInfo = getStoreTypeInfo(type);
|
|
258
|
+
|
|
259
|
+
if (!typeInfo) {
|
|
260
|
+
return {
|
|
261
|
+
metadata: { required: [], optional: [] },
|
|
262
|
+
states: { required: [], optional: [] },
|
|
263
|
+
actions: { required: [], optional: [] },
|
|
264
|
+
subscribeSelector: [],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return {
|
|
269
|
+
metadata: {
|
|
270
|
+
required: typeInfo.metadata.required || [],
|
|
271
|
+
optional: typeInfo.metadata.optional || [],
|
|
272
|
+
},
|
|
273
|
+
states: {
|
|
274
|
+
required: typeInfo.states.required || [],
|
|
275
|
+
optional: typeInfo.states.optional || [],
|
|
276
|
+
},
|
|
277
|
+
actions: {
|
|
278
|
+
required: typeInfo.actions.required || [],
|
|
279
|
+
optional: typeInfo.actions.optional || [],
|
|
280
|
+
},
|
|
281
|
+
subscribeSelector: typeInfo.subscribePattern?.selector || [],
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Get subscribe selector pattern for a specific store type
|
|
287
|
+
*/
|
|
288
|
+
export function getSubscribeSelector(type: number): string[] {
|
|
289
|
+
const typeInfo = getStoreTypeInfo(type);
|
|
290
|
+
if (!typeInfo) {
|
|
291
|
+
return [];
|
|
292
|
+
}
|
|
293
|
+
return typeInfo.subscribePattern?.selector || [];
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Get all field definitions
|
|
298
|
+
*/
|
|
299
|
+
export function getAllFields(): {
|
|
300
|
+
metadata: Record<string, any>;
|
|
301
|
+
states: Record<string, any>;
|
|
302
|
+
actions: Record<string, any>;
|
|
303
|
+
} {
|
|
304
|
+
const docs = loadDocs();
|
|
305
|
+
return docs.patternsJson.fields;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get validation rules
|
|
310
|
+
*/
|
|
311
|
+
export function getValidationRules(): any {
|
|
312
|
+
const docs = loadDocs();
|
|
313
|
+
return docs.rulesJson;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Get forbidden patterns for validation
|
|
318
|
+
*/
|
|
319
|
+
export function getForbiddenPatterns(): any[] {
|
|
320
|
+
const docs = loadDocs();
|
|
321
|
+
return docs.rulesJson.forbiddenPatterns || [];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Get checklist for store generation verification
|
|
326
|
+
*/
|
|
327
|
+
export function getChecklist(): any {
|
|
328
|
+
const docs = loadDocs();
|
|
329
|
+
return docs.rulesJson.checklist || {};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Get required imports for store
|
|
334
|
+
*/
|
|
335
|
+
export function getRequiredImports(): any[] {
|
|
336
|
+
const docs = loadDocs();
|
|
337
|
+
return docs.rulesJson.requiredImports || [];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Get naming rules
|
|
342
|
+
*/
|
|
343
|
+
export function getNamingRules(): any {
|
|
344
|
+
const docs = loadDocs();
|
|
345
|
+
return docs.rulesJson.namingRules || {};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Get implementation rules (e.g., callListApi template)
|
|
350
|
+
*/
|
|
351
|
+
export function getImplementationRules(): any {
|
|
352
|
+
const docs = loadDocs();
|
|
353
|
+
return docs.rulesJson.implementationRules || {};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Get field order for organization
|
|
358
|
+
*/
|
|
359
|
+
export function getFieldOrder(): any {
|
|
360
|
+
const docs = loadDocs();
|
|
361
|
+
return docs.rulesJson.fieldOrder || {};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Get dependencies between fields
|
|
366
|
+
*/
|
|
367
|
+
export function getDependencies(): any {
|
|
368
|
+
const docs = loadDocs();
|
|
369
|
+
return docs.rulesJson.dependencies || {};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Suggest store type based on feature keywords
|
|
374
|
+
*/
|
|
375
|
+
export function suggestStoreType(features: string[]): number {
|
|
376
|
+
const docs = loadDocs();
|
|
377
|
+
const storeTypes = docs.patternsJson.storeTypes;
|
|
378
|
+
|
|
379
|
+
// Count matching features for each type
|
|
380
|
+
const typeScores: Record<number, number> = {};
|
|
381
|
+
|
|
382
|
+
for (const entry of Object.entries(storeTypes)) {
|
|
383
|
+
const typeKey = entry[0] as string;
|
|
384
|
+
const typeInfo = entry[1] as any;
|
|
385
|
+
const typeNum = parseInt(typeKey, 10);
|
|
386
|
+
const allFields = [
|
|
387
|
+
...typeInfo.metadata.required,
|
|
388
|
+
...typeInfo.metadata.optional,
|
|
389
|
+
...typeInfo.actions.required,
|
|
390
|
+
...typeInfo.actions.optional
|
|
391
|
+
];
|
|
392
|
+
|
|
393
|
+
// Count how many features match this type
|
|
394
|
+
let score = 0;
|
|
395
|
+
for (const feature of features) {
|
|
396
|
+
if (allFields.some((field: string) =>
|
|
397
|
+
field.toLowerCase().includes(feature.toLowerCase())
|
|
398
|
+
)) {
|
|
399
|
+
score++;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
typeScores[typeNum] = score;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Return type with highest score, default to 1
|
|
407
|
+
let maxScore = 0;
|
|
408
|
+
let suggestedType = 1;
|
|
409
|
+
|
|
410
|
+
for (const entry of Object.entries(typeScores)) {
|
|
411
|
+
const type = entry[0] as string;
|
|
412
|
+
const score = entry[1] as number;
|
|
413
|
+
if (score > maxScore) {
|
|
414
|
+
maxScore = score;
|
|
415
|
+
suggestedType = parseInt(type, 10);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return suggestedType;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Export a singleton instance
|
|
423
|
+
let cachedDocs: LoadedDocs | null = null;
|
|
424
|
+
|
|
425
|
+
export function getCachedDocs(): LoadedDocs {
|
|
426
|
+
if (!cachedDocs) {
|
|
427
|
+
cachedDocs = loadDocs();
|
|
428
|
+
}
|
|
429
|
+
return cachedDocs;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* 복잡한 요청 여부 판단
|
|
434
|
+
* JSON 매칭 점수가 임계값 미만이거나, 특정 조건에 해당하면 복잡한 요청으로 간주
|
|
435
|
+
*/
|
|
436
|
+
export function isComplexRequest(matchScore: number, extractedFeatures: string[]): boolean {
|
|
437
|
+
// 매칭 점수가 낮으면 복잡한 요청
|
|
438
|
+
if (matchScore < 0.6) {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// 피처가 많으면 복잡한 요청 (5개 이상)
|
|
443
|
+
if (extractedFeatures.length >= 5) {
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// 특정 피처 조합이면 복잡한 요청
|
|
448
|
+
const complexCombinations = [
|
|
449
|
+
['TREE', 'DASHBOARD'],
|
|
450
|
+
['MODAL', 'TREE', 'DETAIL_PANEL'],
|
|
451
|
+
['EXCEL_DOWNLOAD', 'DELETE', 'CHECKBOX'],
|
|
452
|
+
];
|
|
453
|
+
|
|
454
|
+
for (const combo of complexCombinations) {
|
|
455
|
+
if (combo.every(f => extractedFeatures.includes(f))) {
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* 복잡한 요청에 필요한 문서 컨텍스트 반환
|
|
465
|
+
*/
|
|
466
|
+
export function getComplexRequestContext(extractedFeatures: string[]): {
|
|
467
|
+
context: string;
|
|
468
|
+
relevantDocs: string[];
|
|
469
|
+
isComplex: boolean;
|
|
470
|
+
} {
|
|
471
|
+
const docs = getCachedDocs();
|
|
472
|
+
const relevantDocs: string[] = [];
|
|
473
|
+
let context = '';
|
|
474
|
+
|
|
475
|
+
// 항상 포함할 기본 문서
|
|
476
|
+
relevantDocs.push('typeSelection');
|
|
477
|
+
relevantDocs.push('requirementsAnalysis');
|
|
478
|
+
context += `
|
|
479
|
+
## 타입 선택 가이드
|
|
480
|
+
${docs.markdown.typeSelection}
|
|
481
|
+
|
|
482
|
+
## 요구사항 분석 가이드
|
|
483
|
+
${docs.markdown.requirementsAnalysis}
|
|
484
|
+
`;
|
|
485
|
+
|
|
486
|
+
// 피처별 관련 문서 추가
|
|
487
|
+
if (extractedFeatures.includes('TREE')) {
|
|
488
|
+
relevantDocs.push('practicalExamples');
|
|
489
|
+
context += `
|
|
490
|
+
## 실전 예제 (트리 관련)
|
|
491
|
+
${docs.markdown.practicalExamples.split('## ')[2] || ''}
|
|
492
|
+
`;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (extractedFeatures.includes('DASHBOARD')) {
|
|
496
|
+
relevantDocs.push('practicalExamples');
|
|
497
|
+
context += `
|
|
498
|
+
## 실전 예제 (대시보드 관련)
|
|
499
|
+
${docs.markdown.practicalExamples.split('## ')[4] || ''}
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (extractedFeatures.includes('EXCEL_DOWNLOAD')) {
|
|
504
|
+
relevantDocs.push('troubleshooting');
|
|
505
|
+
context += `
|
|
506
|
+
## 엑셀 다운로드 관련 문제 해결
|
|
507
|
+
${docs.markdown.troubleshooting.split('### 2.2')[0] || ''}
|
|
508
|
+
`;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// 문제가 있을 경우 트러블슈팅 추가
|
|
512
|
+
relevantDocs.push('troubleshooting');
|
|
513
|
+
context += `
|
|
514
|
+
## 문제 해결 가이드
|
|
515
|
+
${docs.markdown.troubleshooting}
|
|
516
|
+
`;
|
|
517
|
+
|
|
518
|
+
return { context, relevantDocs, isComplex: true };
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* 단순 요청에 필요한 문서 컨텍스트 반환
|
|
523
|
+
*/
|
|
524
|
+
export function getSimpleRequestContext(recommendedType: number): {
|
|
525
|
+
context: string;
|
|
526
|
+
relevantDocs: string[];
|
|
527
|
+
isComplex: boolean;
|
|
528
|
+
} {
|
|
529
|
+
const docs = getCachedDocs();
|
|
530
|
+
const relevantDocs: string[] = ['quickStart'];
|
|
531
|
+
|
|
532
|
+
const context = `
|
|
533
|
+
## 빠른 시작 가이드
|
|
534
|
+
${docs.markdown.quickStart}
|
|
535
|
+
|
|
536
|
+
## 추천 타입: Type ${recommendedType}
|
|
537
|
+
${getStoreTypeInfo(recommendedType)?.description || ''}
|
|
538
|
+
|
|
539
|
+
## 실전 예제
|
|
540
|
+
${docs.markdown.practicalExamples}
|
|
541
|
+
`;
|
|
542
|
+
|
|
543
|
+
return { context, relevantDocs, isComplex: false };
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* 상황별 적절한 문서 반환
|
|
548
|
+
*/
|
|
549
|
+
export function getContextualDocumentation(
|
|
550
|
+
matchScore: number,
|
|
551
|
+
extractedFeatures: string[],
|
|
552
|
+
recommendedType?: number
|
|
553
|
+
): {
|
|
554
|
+
context: string;
|
|
555
|
+
relevantDocs: string[];
|
|
556
|
+
isComplex: boolean;
|
|
557
|
+
} {
|
|
558
|
+
const isComplex = isComplexRequest(
|
|
559
|
+
matchScore,
|
|
560
|
+
extractedFeatures
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
if (isComplex) {
|
|
564
|
+
return getComplexRequestContext(extractedFeatures);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return getSimpleRequestContext(recommendedType || 1);
|
|
568
|
+
}
|