algokit-mcp 1.0.2 → 1.0.3

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 (102) hide show
  1. package/README.md +138 -16
  2. package/dist/api/boj-scraper.js +1 -1
  3. package/dist/api/boj-scraper.js.map +1 -1
  4. package/dist/api/programmers-scraper.d.ts +0 -5
  5. package/dist/api/programmers-scraper.d.ts.map +1 -1
  6. package/dist/api/programmers-scraper.js +59 -90
  7. package/dist/api/programmers-scraper.js.map +1 -1
  8. package/dist/index.js +38 -35
  9. package/dist/index.js.map +1 -1
  10. package/dist/tools/boj/analyze-code-submission-boj.d.ts +67 -0
  11. package/dist/tools/boj/analyze-code-submission-boj.d.ts.map +1 -0
  12. package/dist/tools/boj/analyze-code-submission-boj.js +91 -0
  13. package/dist/tools/boj/analyze-code-submission-boj.js.map +1 -0
  14. package/dist/tools/boj/analyze-problem-boj.d.ts +48 -0
  15. package/dist/tools/boj/analyze-problem-boj.d.ts.map +1 -0
  16. package/dist/tools/boj/analyze-problem-boj.js +52 -0
  17. package/dist/tools/boj/analyze-problem-boj.js.map +1 -0
  18. package/dist/tools/boj/fetch-problem-content-boj.d.ts +49 -0
  19. package/dist/tools/boj/fetch-problem-content-boj.d.ts.map +1 -0
  20. package/dist/tools/boj/fetch-problem-content-boj.js +95 -0
  21. package/dist/tools/boj/fetch-problem-content-boj.js.map +1 -0
  22. package/dist/tools/boj/generate-hint-boj.d.ts +42 -0
  23. package/dist/tools/boj/generate-hint-boj.d.ts.map +1 -0
  24. package/dist/tools/boj/generate-hint-boj.js +82 -0
  25. package/dist/tools/boj/generate-hint-boj.js.map +1 -0
  26. package/dist/tools/boj/generate-review-template-boj.d.ts +48 -0
  27. package/dist/tools/boj/generate-review-template-boj.d.ts.map +1 -0
  28. package/dist/tools/boj/generate-review-template-boj.js +52 -0
  29. package/dist/tools/boj/generate-review-template-boj.js.map +1 -0
  30. package/dist/tools/boj/get-problem-boj.d.ts +22 -0
  31. package/dist/tools/boj/get-problem-boj.d.ts.map +1 -0
  32. package/dist/tools/boj/get-problem-boj.js +89 -0
  33. package/dist/tools/boj/get-problem-boj.js.map +1 -0
  34. package/dist/tools/boj/search-problems-boj.d.ts +42 -0
  35. package/dist/tools/boj/search-problems-boj.d.ts.map +1 -0
  36. package/dist/tools/boj/search-problems-boj.js +143 -0
  37. package/dist/tools/boj/search-problems-boj.js.map +1 -0
  38. package/dist/tools/boj/search-tags-boj.d.ts +22 -0
  39. package/dist/tools/boj/search-tags-boj.d.ts.map +1 -0
  40. package/dist/tools/boj/search-tags-boj.js +70 -0
  41. package/dist/tools/boj/search-tags-boj.js.map +1 -0
  42. package/dist/tools/get-problem-boj.d.ts +22 -0
  43. package/dist/tools/get-problem-boj.d.ts.map +1 -0
  44. package/dist/tools/get-problem-boj.js +89 -0
  45. package/dist/tools/get-problem-boj.js.map +1 -0
  46. package/dist/tools/programmers/analyze-code-submission-programmers.d.ts +60 -0
  47. package/dist/tools/programmers/analyze-code-submission-programmers.d.ts.map +1 -0
  48. package/dist/tools/programmers/analyze-code-submission-programmers.js +85 -0
  49. package/dist/tools/programmers/analyze-code-submission-programmers.js.map +1 -0
  50. package/dist/tools/programmers/analyze-problem-programmers.d.ts +48 -0
  51. package/dist/tools/programmers/analyze-problem-programmers.d.ts.map +1 -0
  52. package/dist/tools/programmers/analyze-problem-programmers.js +53 -0
  53. package/dist/tools/programmers/analyze-problem-programmers.js.map +1 -0
  54. package/dist/tools/programmers/fetch-problem-content-programmers.d.ts +46 -0
  55. package/dist/tools/programmers/fetch-problem-content-programmers.d.ts.map +1 -0
  56. package/dist/tools/programmers/fetch-problem-content-programmers.js +76 -0
  57. package/dist/tools/programmers/fetch-problem-content-programmers.js.map +1 -0
  58. package/dist/tools/programmers/generate-hint-programmers.d.ts +42 -0
  59. package/dist/tools/programmers/generate-hint-programmers.d.ts.map +1 -0
  60. package/dist/tools/programmers/generate-hint-programmers.js +80 -0
  61. package/dist/tools/programmers/generate-hint-programmers.js.map +1 -0
  62. package/dist/tools/programmers/generate-review-template-programmers.d.ts +48 -0
  63. package/dist/tools/programmers/generate-review-template-programmers.d.ts.map +1 -0
  64. package/dist/tools/programmers/generate-review-template-programmers.js +53 -0
  65. package/dist/tools/programmers/generate-review-template-programmers.js.map +1 -0
  66. package/dist/tools/programmers/get-problem-programmers.d.ts +53 -0
  67. package/dist/tools/programmers/get-problem-programmers.d.ts.map +1 -0
  68. package/dist/tools/programmers/get-problem-programmers.js +163 -0
  69. package/dist/tools/programmers/get-problem-programmers.js.map +1 -0
  70. package/dist/tools/programmers/search-problems-programmers.d.ts +73 -0
  71. package/dist/tools/programmers/search-problems-programmers.d.ts.map +1 -0
  72. package/dist/tools/programmers/search-problems-programmers.js +173 -0
  73. package/dist/tools/programmers/search-problems-programmers.js.map +1 -0
  74. package/dist/tools/search-problems-boj.d.ts +42 -0
  75. package/dist/tools/search-problems-boj.d.ts.map +1 -0
  76. package/dist/tools/search-problems-boj.js +143 -0
  77. package/dist/tools/search-problems-boj.js.map +1 -0
  78. package/dist/tools/search-tags-boj.d.ts +22 -0
  79. package/dist/tools/search-tags-boj.d.ts.map +1 -0
  80. package/dist/tools/search-tags-boj.js +70 -0
  81. package/dist/tools/search-tags-boj.js.map +1 -0
  82. package/dist/utils/agent-skill-installer.d.ts +9 -0
  83. package/dist/utils/agent-skill-installer.d.ts.map +1 -0
  84. package/dist/utils/agent-skill-installer.js +94 -0
  85. package/dist/utils/agent-skill-installer.js.map +1 -0
  86. package/dist/utils/claudecode-skill-installer.d.ts +6 -0
  87. package/dist/utils/claudecode-skill-installer.d.ts.map +1 -0
  88. package/dist/utils/claudecode-skill-installer.js +70 -0
  89. package/dist/utils/claudecode-skill-installer.js.map +1 -0
  90. package/dist/utils/skill-installer.d.ts +6 -0
  91. package/dist/utils/skill-installer.d.ts.map +1 -0
  92. package/dist/utils/skill-installer.js +70 -0
  93. package/dist/utils/skill-installer.js.map +1 -0
  94. package/dist/utils/tier-converter.d.ts.map +1 -1
  95. package/dist/utils/tier-converter.js +3 -0
  96. package/dist/utils/tier-converter.js.map +1 -1
  97. package/package.json +3 -4
  98. package/skills/algo:code-review/SKILL.md +134 -0
  99. package/skills/algo:fetch/SKILL.md +102 -0
  100. package/skills/algo:hint/SKILL.md +111 -0
  101. package/skills/algo:review/SKILL.md +123 -0
  102. package/skills/algo:search/SKILL.md +122 -0
@@ -0,0 +1,173 @@
1
+ /**
2
+ * search_problems_programmers MCP 도구
3
+ *
4
+ * Phase 7 - Task 7.5: 프로그래머스 문제 검색 MCP 도구
5
+ */
6
+ import { z } from 'zod';
7
+ import { ProgrammersScraper } from '../../api/programmers-scraper.js';
8
+ /**
9
+ * 입력 스키마
10
+ */
11
+ export const SearchProgrammersProblemsInputSchema = z.object({
12
+ levels: z.array(z.number().int().min(0).max(5)).optional()
13
+ .describe('난이도 레벨 배열 (0: 입문, 1-5: 레벨1-5). 예: [1, 2] - 레벨1, 2 문제'),
14
+ order: z.enum(['recent', 'accuracy', 'popular']).optional()
15
+ .describe('정렬 방식. recent: 최신순, accuracy: 정확도순, popular: 인기순 (기본값: recent)'),
16
+ page: z.number().int().positive().optional()
17
+ .describe('페이지 번호 (기본값: 1, 페이지당 20개 문제)'),
18
+ limit: z.number().int().positive().max(20).optional()
19
+ .describe('반환할 문제 개수 (최대 20개, 기본값: 20)'),
20
+ query: z.string().optional()
21
+ .describe('검색 키워드 (문제 제목으로 검색)'),
22
+ });
23
+ /**
24
+ * 프로그래머스 문제 검색 도구 핸들러
25
+ *
26
+ * @param args - 입력 인자
27
+ * @returns 문제 목록 (마크다운 테이블 형식)
28
+ * @throws {Error} 검증 실패 또는 스크래핑 실패 시
29
+ */
30
+ export async function searchProgrammersProblems(args) {
31
+ try {
32
+ // 1. 입력 검증
33
+ const input = SearchProgrammersProblemsInputSchema.parse(args);
34
+ // 2. 검색 옵션 구성
35
+ const options = {
36
+ levels: input.levels,
37
+ order: input.order || 'recent',
38
+ page: input.page || 1,
39
+ limit: input.limit || 20,
40
+ query: input.query,
41
+ };
42
+ // 3. 프로그래머스 스크래핑
43
+ const scraper = new ProgrammersScraper();
44
+ const problems = await scraper.searchProblems(options);
45
+ // 4. 결과가 없는 경우
46
+ if (problems.length === 0) {
47
+ return {
48
+ type: 'text',
49
+ text: '🔍 검색 결과가 없습니다.\n\n검색 조건을 변경해보세요.',
50
+ };
51
+ }
52
+ // 5. 마크다운 테이블 생성
53
+ const markdown = formatProblemsAsMarkdown(problems, options);
54
+ return {
55
+ type: 'text',
56
+ text: markdown,
57
+ };
58
+ }
59
+ catch (error) {
60
+ // Zod 검증 에러
61
+ if (error instanceof z.ZodError) {
62
+ throw new Error(`입력 검증 실패: ${error.issues[0].message}`);
63
+ }
64
+ // 기타 에러
65
+ if (error instanceof Error) {
66
+ throw new Error(`프로그래머스 검색 실패: ${error.message}`);
67
+ }
68
+ throw error;
69
+ }
70
+ }
71
+ /**
72
+ * 문제 목록을 마크다운 테이블로 포맷팅
73
+ */
74
+ function formatProblemsAsMarkdown(problems, options) {
75
+ const lines = [];
76
+ // 헤더
77
+ lines.push('# 🔍 프로그래머스 문제 검색 결과\n');
78
+ // 검색 조건 요약
79
+ const conditions = [];
80
+ if (options.levels && options.levels.length > 0) {
81
+ conditions.push(`레벨 ${options.levels.join(', ')}`);
82
+ }
83
+ if (options.query) {
84
+ conditions.push(`키워드 "${options.query}"`);
85
+ }
86
+ if (options.order) {
87
+ const orderName = {
88
+ recent: '최신순',
89
+ accuracy: '정확도순',
90
+ popular: '인기순',
91
+ }[options.order];
92
+ conditions.push(`정렬: ${orderName}`);
93
+ }
94
+ if (conditions.length > 0) {
95
+ lines.push(`**검색 조건**: ${conditions.join(' | ')}\n`);
96
+ }
97
+ lines.push(`**결과**: ${problems.length}개 문제 (페이지 ${options.page || 1})\n`);
98
+ // 테이블 헤더
99
+ lines.push('| 번호 | 제목 | 레벨 | 카테고리 | 완료자 | 정답률 |');
100
+ lines.push('|------|------|------|----------|--------|--------|');
101
+ // 테이블 행
102
+ for (const problem of problems) {
103
+ const title = `[${problem.title}](${problem.url})`;
104
+ const level = formatLevel(problem.level);
105
+ const category = problem.category || '-';
106
+ const finishedCount = problem.finishedCount
107
+ ? problem.finishedCount.toLocaleString()
108
+ : '-';
109
+ const acceptanceRate = problem.acceptanceRate
110
+ ? `${problem.acceptanceRate}%`
111
+ : '-';
112
+ lines.push(`| ${problem.problemId} | ${title} | ${level} | ${category} | ${finishedCount} | ${acceptanceRate} |`);
113
+ }
114
+ lines.push('');
115
+ // 안내 메시지
116
+ lines.push('---');
117
+ lines.push('');
118
+ lines.push('💡 **다음 단계**:');
119
+ lines.push('- 문제를 선택하여 상세 정보 조회: `get_problem_programmers`');
120
+ lines.push('- 문제 분석 및 힌트 생성: `analyze_programmers_problem` (구현 예정)');
121
+ lines.push('');
122
+ lines.push('⚠️ **참고**:');
123
+ lines.push('- 프로그래머스는 페이지당 20개 문제를 반환합니다');
124
+ lines.push('- 실제 프로그래머스 사이트에서 문제를 풀어야 합니다');
125
+ return lines.join('\n');
126
+ }
127
+ /**
128
+ * 레벨을 이모지와 텍스트로 포맷팅
129
+ */
130
+ function formatLevel(level) {
131
+ const levelEmoji = {
132
+ 0: '🟢 입문',
133
+ 1: '🟢 Lv.1',
134
+ 2: '🟡 Lv.2',
135
+ 3: '🟠 Lv.3',
136
+ 4: '🔴 Lv.4',
137
+ 5: '🔴 Lv.5',
138
+ };
139
+ return levelEmoji[level] || `Lv.${level}`;
140
+ }
141
+ /**
142
+ * MCP 도구 정의
143
+ */
144
+ export function searchProgrammersProblemsTool() {
145
+ return {
146
+ name: 'search_problems_programmers',
147
+ description: `프로그래머스 문제를 검색합니다. 난이도, 정렬 방식, 키워드로 필터링할 수 있습니다.
148
+
149
+ **사용 예시**:
150
+ - 레벨 1 문제 검색: levels: [1]
151
+ - 레벨 1-2 문제 검색: levels: [1, 2]
152
+ - 최신 문제 검색: order: "recent"
153
+ - 정확도순 정렬: order: "accuracy"
154
+ - 키워드 검색: query: "동적계획법"
155
+ - 페이지 이동: page: 2
156
+
157
+ **제한사항**:
158
+ - Puppeteer 기반 스크래핑 (응답 시간 3-5초)
159
+ - 페이지당 20개 문제 반환
160
+ - 프로그래머스 레벨 체계: 0(입문), 1-5
161
+
162
+ **응답 형식**:
163
+ - 마크다운 테이블 (번호, 제목, 레벨, 카테고리, 완료자, 정답률)
164
+ - 문제 제목은 프로그래머스 링크로 제공
165
+
166
+ ⚠️ **중요**: 프로그래머스는 JavaScript 렌더링이 필요하여 BOJ보다 느립니다 (3-5초).
167
+
168
+ ⚠️ 플랫폼 미지정 시 사용자에게 어느 플랫폼에서 검색할지 확인하세요.`,
169
+ inputSchema: SearchProgrammersProblemsInputSchema,
170
+ handler: searchProgrammersProblems,
171
+ };
172
+ }
173
+ //# sourceMappingURL=search-problems-programmers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-problems-programmers.js","sourceRoot":"","sources":["../../../src/tools/programmers/search-problems-programmers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * search_problems 도구
3
+ *
4
+ * BOJ 문제를 티어, 태그, 키워드로 검색합니다.
5
+ */
6
+ import { z } from 'zod';
7
+ /**
8
+ * 입력 스키마
9
+ *
10
+ * level_min/level_max는 숫자(1-30) 또는 티어 문자열(예: "실버 3", "Gold I") 모두 지원
11
+ */
12
+ export declare const SearchProblemsInputSchema: z.ZodObject<{
13
+ query: z.ZodOptional<z.ZodString>;
14
+ level_min: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodEffects<z.ZodString, number, string>]>>;
15
+ level_max: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodEffects<z.ZodString, number, string>]>>;
16
+ tags: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
17
+ sort: z.ZodOptional<z.ZodEnum<["level", "id", "average_try"]>>;
18
+ direction: z.ZodOptional<z.ZodEnum<["asc", "desc"]>>;
19
+ page: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ page: number;
22
+ tags?: string | string[] | undefined;
23
+ sort?: "level" | "id" | "average_try" | undefined;
24
+ query?: string | undefined;
25
+ direction?: "asc" | "desc" | undefined;
26
+ level_min?: number | undefined;
27
+ level_max?: number | undefined;
28
+ }, {
29
+ tags?: string | string[] | undefined;
30
+ sort?: "level" | "id" | "average_try" | undefined;
31
+ query?: string | undefined;
32
+ direction?: "asc" | "desc" | undefined;
33
+ page?: number | undefined;
34
+ level_min?: string | number | undefined;
35
+ level_max?: string | number | undefined;
36
+ }>;
37
+ export type SearchProblemsInput = z.infer<typeof SearchProblemsInputSchema>;
38
+ /**
39
+ * 문제 검색 도구 핸들러
40
+ */
41
+ export declare function searchProblems(input: SearchProblemsInput): Promise<string>;
42
+ //# sourceMappingURL=search-problems-boj.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-problems-boj.d.ts","sourceRoot":"","sources":["../../src/tools/search-problems-boj.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;EA+DpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAiD5E;;GAEG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiChF"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * search_problems 도구
3
+ *
4
+ * BOJ 문제를 티어, 태그, 키워드로 검색합니다.
5
+ */
6
+ import { z } from 'zod';
7
+ import { SolvedAcClient } from '../api/solvedac-client.js';
8
+ import { getTierBadge, parseTierString } from '../utils/tier-converter.js';
9
+ /**
10
+ * 입력 스키마
11
+ *
12
+ * level_min/level_max는 숫자(1-30) 또는 티어 문자열(예: "실버 3", "Gold I") 모두 지원
13
+ */
14
+ export const SearchProblemsInputSchema = z.object({
15
+ query: z.string().optional().describe('검색 키워드 (제목, 번호, 태그 등)'),
16
+ level_min: z
17
+ .union([
18
+ z.number().int().min(1).max(30),
19
+ z.string().transform((val, ctx) => {
20
+ // 숫자 문자열이면 숫자로 변환 (예: "16" → 16)
21
+ const numVal = Number(val);
22
+ if (!isNaN(numVal) && Number.isInteger(numVal)) {
23
+ if (numVal < 1 || numVal > 30) {
24
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: '레벨은 1-30 사이여야 합니다.' });
25
+ return z.NEVER;
26
+ }
27
+ return numVal;
28
+ }
29
+ // 티어 문자열 파싱 (예: "실버 3", "Gold I")
30
+ try {
31
+ return parseTierString(val);
32
+ }
33
+ catch (error) {
34
+ ctx.addIssue({
35
+ code: z.ZodIssueCode.custom,
36
+ message: error instanceof Error ? error.message : '티어 파싱 실패',
37
+ });
38
+ return z.NEVER;
39
+ }
40
+ }),
41
+ ])
42
+ .optional()
43
+ .describe('최소 난이도 (숫자 1-30 또는 "실버 3", "Gold I" 형식)'),
44
+ level_max: z
45
+ .union([
46
+ z.number().int().min(1).max(30),
47
+ z.string().transform((val, ctx) => {
48
+ // 숫자 문자열이면 숫자로 변환 (예: "17" → 17)
49
+ const numVal = Number(val);
50
+ if (!isNaN(numVal) && Number.isInteger(numVal)) {
51
+ if (numVal < 1 || numVal > 30) {
52
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: '레벨은 1-30 사이여야 합니다.' });
53
+ return z.NEVER;
54
+ }
55
+ return numVal;
56
+ }
57
+ // 티어 문자열 파싱 (예: "실버 3", "Gold I")
58
+ try {
59
+ return parseTierString(val);
60
+ }
61
+ catch (error) {
62
+ ctx.addIssue({
63
+ code: z.ZodIssueCode.custom,
64
+ message: error instanceof Error ? error.message : '티어 파싱 실패',
65
+ });
66
+ return z.NEVER;
67
+ }
68
+ }),
69
+ ])
70
+ .optional()
71
+ .describe('최대 난이도 (숫자 1-30 또는 "실버 3", "Gold I" 형식)'),
72
+ tags: z
73
+ .union([z.string(), z.array(z.string())])
74
+ .optional()
75
+ .describe('알고리즘 태그 (예: "dp" 또는 ["dp", "greedy", "bfs"])'),
76
+ sort: z.enum(['level', 'id', 'average_try']).optional().describe('정렬 기준'),
77
+ direction: z.enum(['asc', 'desc']).optional().describe('정렬 방향'),
78
+ page: z.number().int().min(1).optional().default(1).describe('페이지 번호 (기본: 1)'),
79
+ });
80
+ /**
81
+ * 한글 태그명 추출
82
+ */
83
+ function getKoreanTagName(tag) {
84
+ const korean = tag.displayNames.find(dn => dn.language === 'ko');
85
+ return korean?.name || tag.key;
86
+ }
87
+ /**
88
+ * 문제 검색 결과를 마크다운 테이블로 포맷팅
89
+ */
90
+ function formatSearchResults(items, count, page) {
91
+ if (items.length === 0) {
92
+ return '검색 결과가 없습니다.';
93
+ }
94
+ let result = `# 문제 검색 결과\n\n`;
95
+ result += `**총 ${count}개 문제** (${page}페이지)\n\n`;
96
+ result += `| 번호 | 제목 | 난이도 | 태그 | 해결자 수 | 평균 시도 |\n`;
97
+ result += `|------|------|--------|------|-----------|----------|\n`;
98
+ for (const problem of items) {
99
+ const tierBadge = getTierBadge(problem.level);
100
+ const tags = problem.tags.slice(0, 3).map(getKoreanTagName).join(', ');
101
+ const tagsDisplay = problem.tags.length > 3 ? `${tags}...` : tags;
102
+ const bojLink = `https://www.acmicpc.net/problem/${problem.problemId}`;
103
+ result += `| [${problem.problemId}](${bojLink}) | ${problem.titleKo} | ${tierBadge} | ${tagsDisplay} | ${problem.acceptedUserCount.toLocaleString()}명 | ${problem.averageTries.toFixed(1)}회 |\n`;
104
+ }
105
+ result += `\n---\n`;
106
+ result += `💡 **팁**: 문제 번호를 클릭하면 BOJ 페이지로 이동합니다.\n`;
107
+ return result;
108
+ }
109
+ /**
110
+ * 문제 검색 도구 핸들러
111
+ */
112
+ export async function searchProblems(input) {
113
+ // 입력 검증
114
+ if (input.level_min !== undefined && input.level_max !== undefined) {
115
+ if (input.level_min > input.level_max) {
116
+ throw new Error('level_min은 level_max보다 작거나 같아야 합니다.');
117
+ }
118
+ }
119
+ const client = new SolvedAcClient();
120
+ try {
121
+ // API 호출
122
+ const params = {
123
+ query: input.query,
124
+ level_min: input.level_min,
125
+ level_max: input.level_max,
126
+ tags: input.tags,
127
+ sort: input.sort,
128
+ direction: input.direction,
129
+ page: input.page,
130
+ };
131
+ const result = await client.searchProblems(params);
132
+ // 결과 포맷팅
133
+ return formatSearchResults(result.items, result.count, input.page);
134
+ }
135
+ catch (error) {
136
+ // 에러 메시지 포맷팅
137
+ if (error instanceof Error) {
138
+ throw new Error(`문제 검색 중 오류가 발생했습니다: ${error.message}`);
139
+ }
140
+ throw new Error('문제 검색 중 알 수 없는 오류가 발생했습니다.');
141
+ }
142
+ }
143
+ //# sourceMappingURL=search-problems-boj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-problems-boj.js","sourceRoot":"","sources":["../../src/tools/search-problems-boj.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * search_tags 도구
3
+ *
4
+ * 알고리즘 태그를 키워드로 검색합니다.
5
+ */
6
+ import { z } from 'zod';
7
+ /**
8
+ * 입력 스키마
9
+ */
10
+ export declare const SearchTagsInputSchema: z.ZodObject<{
11
+ query: z.ZodString;
12
+ }, "strip", z.ZodTypeAny, {
13
+ query: string;
14
+ }, {
15
+ query: string;
16
+ }>;
17
+ export type SearchTagsInput = z.infer<typeof SearchTagsInputSchema>;
18
+ /**
19
+ * 태그 검색 도구 핸들러
20
+ */
21
+ export declare function searchTags(input: SearchTagsInput): Promise<string>;
22
+ //# sourceMappingURL=search-tags-boj.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tags-boj.d.ts","sourceRoot":"","sources":["../../src/tools/search-tags-boj.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;EAEhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AA0CpE;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBxE"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * search_tags 도구
3
+ *
4
+ * 알고리즘 태그를 키워드로 검색합니다.
5
+ */
6
+ import { z } from 'zod';
7
+ import { SolvedAcClient } from '../api/solvedac-client.js';
8
+ /**
9
+ * 입력 스키마
10
+ */
11
+ export const SearchTagsInputSchema = z.object({
12
+ query: z.string().min(1).describe('태그 검색 키워드 (최소 1글자)'),
13
+ });
14
+ /**
15
+ * 다국어 태그명 추출
16
+ */
17
+ function getTagNames(tag) {
18
+ const korean = tag.displayNames.find(dn => dn.language === 'ko')?.name || tag.key;
19
+ const english = tag.displayNames.find(dn => dn.language === 'en')?.name || tag.key;
20
+ return { korean, english };
21
+ }
22
+ /**
23
+ * 태그 검색 결과를 마크다운 테이블로 포맷팅
24
+ */
25
+ function formatTagResults(tags) {
26
+ if (tags.length === 0) {
27
+ return '검색 결과가 없습니다. 다른 키워드로 시도해보세요.';
28
+ }
29
+ let result = `# 태그 검색 결과\n\n`;
30
+ result += `**총 ${tags.length}개 태그**\n\n`;
31
+ result += `| 태그 키 | 한글명 | 영문명 | 문제 수 |\n`;
32
+ result += `|---------|--------|--------|----------|\n`;
33
+ for (const tag of tags) {
34
+ const { korean, english } = getTagNames(tag);
35
+ const problemCount = tag.problemCount ? tag.problemCount.toLocaleString() : '-';
36
+ result += `| \`${tag.key}\` | ${korean} | ${english} | ${problemCount}개 |\n`;
37
+ }
38
+ result += `\n---\n`;
39
+ result += `💡 **팁**: 태그 키를 사용하여 \`search_problems\` 도구로 해당 태그의 문제를 검색할 수 있습니다.\n`;
40
+ result += `\n**사용 예시**:\n`;
41
+ result += `\`\`\`\n`;
42
+ result += `search_problems(tag: "${tags[0]?.key || 'dp'}")\n`;
43
+ result += `\`\`\`\n`;
44
+ return result;
45
+ }
46
+ /**
47
+ * 태그 검색 도구 핸들러
48
+ */
49
+ export async function searchTags(input) {
50
+ // 입력 검증 (공백 제거)
51
+ const query = input.query.trim();
52
+ if (query.length === 0) {
53
+ throw new Error('검색 키워드는 최소 1글자 이상이어야 합니다.');
54
+ }
55
+ const client = new SolvedAcClient();
56
+ try {
57
+ // API 호출
58
+ const tags = await client.searchTags(query);
59
+ // 결과 포맷팅
60
+ return formatTagResults(tags);
61
+ }
62
+ catch (error) {
63
+ // 에러 처리
64
+ if (error instanceof Error) {
65
+ throw new Error(`태그 검색 중 오류가 발생했습니다: ${error.message}`);
66
+ }
67
+ throw new Error('태그 검색 중 알 수 없는 오류가 발생했습니다.');
68
+ }
69
+ }
70
+ //# sourceMappingURL=search-tags-boj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tags-boj.js","sourceRoot":"","sources":["../../src/tools/search-tags-boj.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 감지된 모든 AI 에이전트 플랫폼에 스킬을 설치합니다.
3
+ *
4
+ * - 설치된 플랫폼만 대상으로 함 (미설치 플랫폼은 건너뜀)
5
+ * - 로컬/전역 등록 방식에 따라 적절한 경로에 설치
6
+ * - 버전이 같으면 재설치 없이 건너뜀
7
+ */
8
+ export declare function ensureSkillsInstalled(): Promise<void>;
9
+ //# sourceMappingURL=agent-skill-installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-skill-installer.d.ts","sourceRoot":"","sources":["../../src/utils/agent-skill-installer.ts"],"names":[],"mappings":"AAoFA;;;;;;GAMG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc3D"}
@@ -0,0 +1,94 @@
1
+ import { existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';
2
+ import { mkdir, cp } from 'fs/promises';
3
+ import { join, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { homedir } from 'os';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ /**
9
+ * 지원하는 AI 에이전트 플랫폼 정의
10
+ *
11
+ * 각 플랫폼의 스킬 경로 결정 규칙:
12
+ * - 로컬 설정 디렉토리가 cwd에 있으면 → 로컬 스킬 경로
13
+ * - 전역 홈 디렉토리가 있으면 → 전역 스킬 경로
14
+ *
15
+ * | 플랫폼 | 로컬 감지 기준 | 로컬 스킬 경로 | 전역 스킬 경로 |
16
+ * |------------|---------------------|----------------------|----------------------|
17
+ * | Claude Code | .mcp.json | .claude/skills/ | ~/.claude/skills/ |
18
+ * | Codex CLI | .codex/ | .codex/skills/ | ~/.codex/skills/ |
19
+ * | Gemini CLI | .gemini/ | .gemini/skills/ | ~/.gemini/skills/ |
20
+ *
21
+ * Codex 참고: 프로젝트 Skills 표준 경로는 .agents/skills/ (cwd → repo root 스캔)
22
+ * Gemini 참고: .agents/skills/도 alias로 지원하나 .gemini/skills/ 권장
23
+ */
24
+ const PLATFORMS = [
25
+ {
26
+ name: 'Claude Code',
27
+ localIndicator: join(process.cwd(), '.mcp.json'),
28
+ localSkillsDir: join(process.cwd(), '.claude', 'skills'),
29
+ globalHomeDir: join(homedir(), '.claude'),
30
+ globalSkillsDir: join(homedir(), '.claude', 'skills'),
31
+ },
32
+ {
33
+ name: 'Codex',
34
+ localIndicator: join(process.cwd(), '.codex'),
35
+ localSkillsDir: join(process.cwd(), '.codex', 'skills'),
36
+ globalHomeDir: join(homedir(), '.codex'),
37
+ globalSkillsDir: join(homedir(), '.codex', 'skills'),
38
+ },
39
+ {
40
+ name: 'Gemini',
41
+ localIndicator: join(process.cwd(), '.gemini'),
42
+ localSkillsDir: join(process.cwd(), '.gemini', 'skills'),
43
+ globalHomeDir: join(homedir(), '.gemini'),
44
+ globalSkillsDir: join(homedir(), '.gemini', 'skills'),
45
+ },
46
+ ];
47
+ /** 플랫폼별 스킬을 설치할 대상 경로를 결정합니다. */
48
+ function resolveTargetDir(platform) {
49
+ if (existsSync(platform.localIndicator))
50
+ return platform.localSkillsDir;
51
+ if (existsSync(platform.globalHomeDir))
52
+ return platform.globalSkillsDir;
53
+ return null; // 해당 플랫폼 미설치
54
+ }
55
+ /** 스킬 디렉토리에 algokit 스킬을 복사합니다. 이미 같은 버전이면 건너뜁니다. */
56
+ async function installSkillsTo(skillsSrc, targetDir, version, platformName) {
57
+ const versionFile = join(targetDir, '.algokit-skills-version');
58
+ if (existsSync(versionFile)) {
59
+ const installed = readFileSync(versionFile, 'utf-8').trim();
60
+ if (installed === version)
61
+ return;
62
+ }
63
+ await mkdir(targetDir, { recursive: true });
64
+ // 기존 다른 스킬을 건드리지 않도록 algokit 스킬 디렉토리만 선택적 복사
65
+ for (const skillDir of readdirSync(skillsSrc)) {
66
+ await cp(join(skillsSrc, skillDir), join(targetDir, skillDir), {
67
+ recursive: true,
68
+ force: true,
69
+ });
70
+ }
71
+ writeFileSync(versionFile, version);
72
+ process.stderr.write(`[algokit] skills v${version} installed → ${targetDir} (${platformName})\n`);
73
+ }
74
+ /**
75
+ * 감지된 모든 AI 에이전트 플랫폼에 스킬을 설치합니다.
76
+ *
77
+ * - 설치된 플랫폼만 대상으로 함 (미설치 플랫폼은 건너뜀)
78
+ * - 로컬/전역 등록 방식에 따라 적절한 경로에 설치
79
+ * - 버전이 같으면 재설치 없이 건너뜀
80
+ */
81
+ export async function ensureSkillsInstalled() {
82
+ const skillsSrc = join(__dirname, '../../skills');
83
+ if (!existsSync(skillsSrc))
84
+ return;
85
+ const pkgPath = join(__dirname, '../../package.json');
86
+ const { version } = JSON.parse(readFileSync(pkgPath, 'utf-8'));
87
+ await Promise.all(PLATFORMS.map(async (platform) => {
88
+ const targetDir = resolveTargetDir(platform);
89
+ if (!targetDir)
90
+ return;
91
+ await installSkillsTo(skillsSrc, targetDir, version, platform.name);
92
+ }));
93
+ }
94
+ //# sourceMappingURL=agent-skill-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-skill-installer.js","sourceRoot":"","sources":["../../src/utils/agent-skill-installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 패키지에 동봉된 skills/를 적절한 위치에 설치합니다.
3
+ * Claude Code 환경이 아니거나 이미 같은 버전이 설치되어 있으면 건너뜁니다.
4
+ */
5
+ export declare function ensureSkillsInstalled(): Promise<void>;
6
+ //# sourceMappingURL=claudecode-skill-installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudecode-skill-installer.d.ts","sourceRoot":"","sources":["../../src/utils/claudecode-skill-installer.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiC3D"}