@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.
Files changed (78) hide show
  1. package/CLAUDE.md +119 -0
  2. package/MCP_TOOL_PLAN.md +710 -0
  3. package/MCP_USAGE.md +914 -0
  4. package/README.md +168 -0
  5. package/REPOSITORY_CONVENTIONS.md +250 -0
  6. package/SEARCH_PARAMS_MCP_TOOL_COMPLETE_PLAN.md +646 -0
  7. package/SEARCH_PARAMS_PLAN.md +2570 -0
  8. package/STORE_PATTERNS.md +1178 -0
  9. package/debug-dto.js +72 -0
  10. package/generate-banner-store.js +62 -0
  11. package/generation-plan.json +2176 -0
  12. package/generation-results.json +1817 -0
  13. package/package.json +45 -0
  14. package/scripts/batch-generate-all.js +159 -0
  15. package/scripts/batch-generate-mcp.js +329 -0
  16. package/scripts/batch-generate-stores-v2.js +272 -0
  17. package/scripts/batch-generate-stores.js +179 -0
  18. package/scripts/batch-plan.json +3810 -0
  19. package/scripts/batch-process.py +90 -0
  20. package/scripts/batch-regenerate.js +356 -0
  21. package/scripts/direct-generate.js +227 -0
  22. package/scripts/execute-batches.js +1911 -0
  23. package/scripts/generate-all-stores.js +144 -0
  24. package/scripts/generate-stores-mcp.js +161 -0
  25. package/scripts/generate-stores-v2.js +450 -0
  26. package/scripts/generate-stores-v3.js +412 -0
  27. package/scripts/generate-stores-v4.js +521 -0
  28. package/scripts/generate-stores.js +382 -0
  29. package/scripts/repos-to-process.json +1899 -0
  30. package/src/config/nh-layout-patterns.ts +166 -0
  31. package/src/docs/HOOK_GENERATION_PLAN.md +2226 -0
  32. package/src/docs/NH_STORE_PATTERNS.md +297 -0
  33. package/src/docs/README.md +216 -0
  34. package/src/docs/index.ts +28 -0
  35. package/src/docs/loader.ts +568 -0
  36. package/src/docs/patterns.json +419 -0
  37. package/src/docs/practical-examples.md +732 -0
  38. package/src/docs/quick-start.md +257 -0
  39. package/src/docs/requirements-analysis-guide.md +364 -0
  40. package/src/docs/rules.json +321 -0
  41. package/src/docs/store-pattern-analysis.md +664 -0
  42. package/src/docs/store-patterns-rules.md +1168 -0
  43. package/src/docs/store-patterns-usage-guide.md +1835 -0
  44. package/src/docs/troubleshooting.md +544 -0
  45. package/src/docs/type-selection-guide.md +572 -0
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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
  56. 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
  57. package/src/features/store-features.ts +232 -0
  58. package/src/handlers/analyze-requirements.ts +403 -0
  59. package/src/handlers/analyze.ts +1373 -0
  60. package/src/handlers/generate-from-requirements.ts +250 -0
  61. package/src/handlers/generate-hook.ts +950 -0
  62. package/src/handlers/generate-interactive.ts +840 -0
  63. package/src/handlers/generate-listdatagrid.ts +521 -0
  64. package/src/handlers/generate-multi-stores.ts +577 -0
  65. package/src/handlers/generate-requirements-from-layout.ts +160 -0
  66. package/src/handlers/generate-search-params.ts +717 -0
  67. package/src/handlers/generate.ts +911 -0
  68. package/src/handlers/list-templates.ts +104 -0
  69. package/src/handlers/scan-metadata.ts +485 -0
  70. package/src/handlers/suggest-layout.ts +326 -0
  71. package/src/index.ts +959 -0
  72. package/src/prompts/search-params.md +793 -0
  73. package/src/templates/index.ts +107 -0
  74. package/src/templates/unified.ts +462 -0
  75. package/store-generation-error-patterns.md +225 -0
  76. package/test/useAgentStore.ts +136 -0
  77. package/test-server.js +78 -0
  78. 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
+ }