mne-docs-mcp 1.0.47 → 1.0.49
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/archive/manager.d.ts +7 -0
- package/dist/archive/manager.d.ts.map +1 -1
- package/dist/archive/manager.js +46 -1
- package/dist/archive/manager.js.map +1 -1
- package/dist/archive/search.d.ts +5 -0
- package/dist/archive/search.d.ts.map +1 -1
- package/dist/archive/search.js +15 -0
- package/dist/archive/search.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/forum/client.d.ts +32 -1
- package/dist/forum/client.d.ts.map +1 -1
- package/dist/forum/client.js +139 -7
- package/dist/forum/client.js.map +1 -1
- package/dist/github/client.d.ts +7 -1
- package/dist/github/client.d.ts.map +1 -1
- package/dist/github/client.js +75 -12
- package/dist/github/client.js.map +1 -1
- package/dist/github/types.d.ts +6 -0
- package/dist/github/types.d.ts.map +1 -1
- package/dist/repoContent/index.d.ts +3 -0
- package/dist/repoContent/index.d.ts.map +1 -1
- package/dist/repoContent/index.js +14 -8
- package/dist/repoContent/index.js.map +1 -1
- package/dist/searchCorpus/index.d.ts +3 -0
- package/dist/searchCorpus/index.d.ts.map +1 -1
- package/dist/searchCorpus/index.js +62 -19
- package/dist/searchCorpus/index.js.map +1 -1
- package/dist/symbolLookup/index.d.ts +2 -0
- package/dist/symbolLookup/index.d.ts.map +1 -1
- package/dist/symbolLookup/index.js +65 -18
- package/dist/symbolLookup/index.js.map +1 -1
- package/dist/tools/defineTool.d.ts +18 -0
- package/dist/tools/defineTool.d.ts.map +1 -0
- package/dist/tools/defineTool.js +8 -0
- package/dist/tools/defineTool.js.map +1 -0
- package/dist/tools/findMneSymbol.d.ts +6 -10
- package/dist/tools/findMneSymbol.d.ts.map +1 -1
- package/dist/tools/findMneSymbol.js +10 -15
- package/dist/tools/findMneSymbol.js.map +1 -1
- package/dist/tools/getMneChangelog.d.ts +6 -10
- package/dist/tools/getMneChangelog.d.ts.map +1 -1
- package/dist/tools/getMneChangelog.js +54 -13
- package/dist/tools/getMneChangelog.js.map +1 -1
- package/dist/tools/getMneDoc.d.ts +7 -10
- package/dist/tools/getMneDoc.d.ts.map +1 -1
- package/dist/tools/getMneDoc.js +51 -35
- package/dist/tools/getMneDoc.js.map +1 -1
- package/dist/tools/getMneExample.d.ts +12 -12
- package/dist/tools/getMneExample.d.ts.map +1 -1
- package/dist/tools/getMneExample.js +34 -20
- package/dist/tools/getMneExample.js.map +1 -1
- package/dist/tools/getMneFile.d.ts +7 -11
- package/dist/tools/getMneFile.d.ts.map +1 -1
- package/dist/tools/getMneFile.js +131 -40
- package/dist/tools/getMneFile.js.map +1 -1
- package/dist/tools/getMneForumTopic.d.ts +8 -37
- package/dist/tools/getMneForumTopic.d.ts.map +1 -1
- package/dist/tools/getMneForumTopic.js +8 -132
- package/dist/tools/getMneForumTopic.js.map +1 -1
- package/dist/tools/getMneIssue.d.ts +8 -10
- package/dist/tools/getMneIssue.d.ts.map +1 -1
- package/dist/tools/getMneIssue.js +16 -10
- package/dist/tools/getMneIssue.js.map +1 -1
- package/dist/tools/getMneIssueComments.d.ts +10 -10
- package/dist/tools/getMneIssueComments.d.ts.map +1 -1
- package/dist/tools/getMneIssueComments.js +30 -13
- package/dist/tools/getMneIssueComments.js.map +1 -1
- package/dist/tools/getRelatedSymbols.d.ts +7 -11
- package/dist/tools/getRelatedSymbols.d.ts.map +1 -1
- package/dist/tools/getRelatedSymbols.js +44 -18
- package/dist/tools/getRelatedSymbols.js.map +1 -1
- package/dist/tools/getSymbolReferences.d.ts +7 -10
- package/dist/tools/getSymbolReferences.d.ts.map +1 -1
- package/dist/tools/getSymbolReferences.js +28 -16
- package/dist/tools/getSymbolReferences.js.map +1 -1
- package/dist/tools/listMneVersions.d.ts +6 -63
- package/dist/tools/listMneVersions.d.ts.map +1 -1
- package/dist/tools/listMneVersions.js +13 -15
- package/dist/tools/listMneVersions.js.map +1 -1
- package/dist/tools/lookupMneError.d.ts +14 -10
- package/dist/tools/lookupMneError.d.ts.map +1 -1
- package/dist/tools/lookupMneError.js +69 -14
- package/dist/tools/lookupMneError.js.map +1 -1
- package/dist/tools/requestBudget.d.ts +12 -0
- package/dist/tools/requestBudget.d.ts.map +1 -0
- package/dist/tools/requestBudget.js +36 -0
- package/dist/tools/requestBudget.js.map +1 -0
- package/dist/tools/searchMneDocs.d.ts +5 -9
- package/dist/tools/searchMneDocs.d.ts.map +1 -1
- package/dist/tools/searchMneDocs.js +162 -22
- package/dist/tools/searchMneDocs.js.map +1 -1
- package/dist/tools/searchMneForum.d.ts +9 -10
- package/dist/tools/searchMneForum.d.ts.map +1 -1
- package/dist/tools/searchMneForum.js +21 -12
- package/dist/tools/searchMneForum.js.map +1 -1
- package/dist/tools/searchMneIssues.d.ts +10 -11
- package/dist/tools/searchMneIssues.d.ts.map +1 -1
- package/dist/tools/searchMneIssues.js +28 -24
- package/dist/tools/searchMneIssues.js.map +1 -1
- package/dist/types.d.ts +53 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/helpers.d.ts +5 -2
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +26 -5
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/html.d.ts +2 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +21 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/publicSymbols.d.ts +12 -0
- package/dist/utils/publicSymbols.d.ts.map +1 -0
- package/dist/utils/publicSymbols.js +72 -0
- package/dist/utils/publicSymbols.js.map +1 -0
- package/dist/utils/searchRanking.d.ts +18 -0
- package/dist/utils/searchRanking.d.ts.map +1 -0
- package/dist/utils/searchRanking.js +63 -0
- package/dist/utils/searchRanking.js.map +1 -0
- package/dist/utils/symbolResolver.d.ts.map +1 -1
- package/dist/utils/symbolResolver.js +29 -1
- package/dist/utils/symbolResolver.js.map +1 -1
- package/package.json +1 -1
- package/python/ast_extractor.py +3 -0
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ToolContext } from '../types.js';
|
|
2
|
+
import { GetMneFileResult, ToolContext } from '../types.js';
|
|
3
3
|
export declare const definition: {
|
|
4
|
-
name: string;
|
|
5
|
-
title: string;
|
|
6
|
-
description: string;
|
|
7
4
|
inputSchema: {
|
|
8
5
|
path: z.ZodString;
|
|
9
6
|
version: z.ZodOptional<z.ZodString>;
|
|
@@ -12,13 +9,12 @@ export declare const definition: {
|
|
|
12
9
|
endLine: z.ZodOptional<z.ZodNumber>;
|
|
13
10
|
package: z.ZodOptional<z.ZodEnum<[string, ...string[]]>>;
|
|
14
11
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
12
|
+
name: string;
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
annotations?: object;
|
|
16
|
+
outputSchema?: z.ZodTypeAny;
|
|
21
17
|
};
|
|
22
|
-
export declare function getMneFile(params: unknown, context: ToolContext): Promise<
|
|
18
|
+
export declare function getMneFile(params: unknown, context: ToolContext): Promise<GetMneFileResult>;
|
|
23
19
|
export { getMneFile as handler };
|
|
24
20
|
//# sourceMappingURL=getMneFile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMneFile.d.ts","sourceRoot":"","sources":["../../src/tools/getMneFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAY,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"getMneFile.d.ts","sourceRoot":"","sources":["../../src/tools/getMneFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAY,WAAW,EAAE,MAAM,aAAa,CAAC;AAoBtE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;CAMrB,CAAC;AAEH,wBAAsB,UAAU,CAC5B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,WAAW,GACrB,OAAO,CAAC,gBAAgB,CAAC,CAmE3B;AAyHD,OAAO,EAAE,UAAU,IAAI,OAAO,EAAE,CAAC"}
|
package/dist/tools/getMneFile.js
CHANGED
|
@@ -1,62 +1,87 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { McpError } from '../types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { packageSchema } from '../config.js';
|
|
4
4
|
import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
import { getCachedArchive, findFilesInArchive } from '../archive/search.js';
|
|
6
|
+
import { buildGithubRequestBudget } from './requestBudget.js';
|
|
7
|
+
import { defineTool } from './defineTool.js';
|
|
8
|
+
const GetMneFileParamsBaseSchema = z.object({
|
|
9
|
+
path: z.string().trim().min(1, 'Path is required').describe('File path in repo, e.g. "mne/epochs.py" or "mne_bids/write.py"'),
|
|
10
|
+
version: z.string().optional().describe('Version tag, e.g. "1.6.0" (default: latest)'),
|
|
11
|
+
maxLines: z.number().int().positive().optional().describe('Truncate output to N lines'),
|
|
12
|
+
startLine: z.number().int().positive().optional().describe('Start from this line number'),
|
|
13
|
+
endLine: z.number().int().positive().optional().describe('End at this line number'),
|
|
14
|
+
package: packageSchema,
|
|
12
15
|
});
|
|
13
|
-
|
|
16
|
+
const GetMneFileParamsSchema = GetMneFileParamsBaseSchema.refine(params => params.startLine === undefined || params.endLine === undefined || params.startLine <= params.endLine, { path: ['endLine'], message: 'endLine must be greater than or equal to startLine' });
|
|
17
|
+
export const definition = defineTool({
|
|
14
18
|
name: 'get_mne_file',
|
|
15
19
|
title: 'Get MNE File',
|
|
16
20
|
description: 'Fetch raw source code from MNE-Python or related package repositories. Use when you need to see the actual implementation of a function or class.',
|
|
17
|
-
|
|
18
|
-
path: z.string().describe('File path in repo, e.g. "mne/epochs.py" or "mne_bids/write.py"'),
|
|
19
|
-
version: z.string().optional().describe('Version tag, e.g. "1.6.0" (default: latest)'),
|
|
20
|
-
maxLines: z.number().int().positive().optional().describe('Truncate output to N lines'),
|
|
21
|
-
startLine: z.number().int().positive().optional().describe('Start from this line number'),
|
|
22
|
-
endLine: z.number().int().positive().optional().describe('End at this line number'),
|
|
23
|
-
package: packageSchema,
|
|
24
|
-
},
|
|
21
|
+
paramsSchema: GetMneFileParamsBaseSchema,
|
|
25
22
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
26
|
-
};
|
|
23
|
+
});
|
|
27
24
|
export async function getMneFile(params, context) {
|
|
28
25
|
const { path, version, maxLines, startLine, endLine, package: packageName } = GetMneFileParamsSchema.parse(params);
|
|
26
|
+
const normalizedPath = normalizeRepoPath(path);
|
|
27
|
+
if (!normalizedPath) {
|
|
28
|
+
throw new McpError('FILE_NOT_FOUND', 'File path is empty after normalization', {
|
|
29
|
+
suggestion: 'Pass a repository-relative path such as "mne/epochs.py".',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
29
32
|
const target = await context.repoContent.resolveTarget({ version, packageName });
|
|
30
|
-
const file = await context.repoContent.readFile({ path, target });
|
|
33
|
+
const file = await context.repoContent.readFile({ path: normalizedPath, target });
|
|
31
34
|
if (file === null) {
|
|
32
35
|
// Best-effort fallback: try to find close matches in the same repo
|
|
33
36
|
// so that callers get concrete alternative paths instead of a bare
|
|
34
37
|
// "FILE_NOT_FOUND" error.
|
|
35
38
|
let suggestion = 'Check the file path and version. Use search_mne_docs to find available files.';
|
|
36
39
|
let details = `Package: ${target.packageName}, Version: ${target.version}`;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
43
|
-
if (search.total_count > 0 && search.items?.length) {
|
|
44
|
-
const candidates = search.items.slice(0, 5).map(item => `- ${item.path}`);
|
|
45
|
-
suggestion =
|
|
46
|
-
'File not found at the requested path. Here are the closest matching files in this repository.';
|
|
47
|
-
details = `${details}\nClosest matches:\n${candidates.join('\n')}`;
|
|
48
|
-
}
|
|
40
|
+
const archiveMatches = await findCloseArchivePathMatches(normalizedPath, target.version, target.packageName, context);
|
|
41
|
+
if (archiveMatches.length > 0) {
|
|
42
|
+
suggestion =
|
|
43
|
+
'File not found at the requested path. Here are the closest matching files in this repository.';
|
|
44
|
+
details = `${details}\nClosest matches:\n${archiveMatches.map(match => `- ${match}`).join('\n')}`;
|
|
49
45
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
else {
|
|
47
|
+
try {
|
|
48
|
+
const fileName = normalizedPath.split('/').pop() || normalizedPath;
|
|
49
|
+
const search = await context.github.searchCode(fileName, {
|
|
50
|
+
packageName: target.packageName,
|
|
51
|
+
perPage: 5,
|
|
52
|
+
});
|
|
53
|
+
if (search.total_count > 0 && search.items?.length) {
|
|
54
|
+
const candidates = search.items.slice(0, 5).map(item => `- ${item.path}`);
|
|
55
|
+
suggestion =
|
|
56
|
+
'File not found at the requested path. Here are the closest matching files in this repository.';
|
|
57
|
+
details = `${details}\nClosest matches:\n${candidates.join('\n')}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// If the fallback search fails (e.g. rate-limit), fall through to the
|
|
62
|
+
// original generic suggestion without overwriting it.
|
|
63
|
+
}
|
|
53
64
|
}
|
|
54
|
-
throw new McpError('FILE_NOT_FOUND', `File not found: ${
|
|
65
|
+
throw new McpError('FILE_NOT_FOUND', `File not found: ${normalizedPath}`, {
|
|
55
66
|
details,
|
|
56
67
|
suggestion,
|
|
57
68
|
});
|
|
58
69
|
}
|
|
59
|
-
|
|
70
|
+
const extracted = extractContent(file.content, { maxLines, startLine, endLine });
|
|
71
|
+
const totalLines = file.content.split('\n').length;
|
|
72
|
+
return {
|
|
73
|
+
path: file.path,
|
|
74
|
+
version: file.version,
|
|
75
|
+
package: file.packageName,
|
|
76
|
+
sourceUrl: context.repoContent.sourceUrl(target, file.path, extracted.startLine, extracted.endLine),
|
|
77
|
+
content: extracted.content,
|
|
78
|
+
totalLines,
|
|
79
|
+
startLine: extracted.startLine,
|
|
80
|
+
endLine: extracted.endLine,
|
|
81
|
+
truncated: extracted.truncated,
|
|
82
|
+
fetchSource: file.readSource,
|
|
83
|
+
requestBudget: buildGithubRequestBudget(context.github, ['core', 'code']),
|
|
84
|
+
};
|
|
60
85
|
}
|
|
61
86
|
function extractContent(content, options) {
|
|
62
87
|
const { maxLines, startLine, endLine } = options;
|
|
@@ -74,12 +99,78 @@ function extractContent(content, options) {
|
|
|
74
99
|
if (end < totalLines) {
|
|
75
100
|
result += `\n... (ended at line ${end}, total ${totalLines} lines)`;
|
|
76
101
|
}
|
|
77
|
-
return
|
|
102
|
+
return {
|
|
103
|
+
content: result,
|
|
104
|
+
startLine: start + 1,
|
|
105
|
+
endLine: end,
|
|
106
|
+
truncated: start > 0 || end < totalLines,
|
|
107
|
+
};
|
|
78
108
|
}
|
|
79
109
|
// Otherwise use maxLines truncation
|
|
80
|
-
if (!maxLines || lines.length <= maxLines)
|
|
81
|
-
return
|
|
82
|
-
|
|
110
|
+
if (!maxLines || lines.length <= maxLines) {
|
|
111
|
+
return {
|
|
112
|
+
content,
|
|
113
|
+
startLine: 1,
|
|
114
|
+
endLine: totalLines,
|
|
115
|
+
truncated: false,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
content: lines.slice(0, maxLines).join('\n') + `\n... (truncated after ${maxLines} lines, total ${totalLines} lines)`,
|
|
120
|
+
startLine: 1,
|
|
121
|
+
endLine: maxLines,
|
|
122
|
+
truncated: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function normalizeRepoPath(path) {
|
|
126
|
+
return path.replace(/\\/g, '/').replace(/^\/+/, '').replace(/\/{2,}/g, '/');
|
|
127
|
+
}
|
|
128
|
+
async function findCloseArchivePathMatches(requestedPath, version, packageName, context) {
|
|
129
|
+
const archive = await getCachedArchive(context.github, context.archive, version, packageName);
|
|
130
|
+
if (!archive)
|
|
131
|
+
return [];
|
|
132
|
+
const extension = requestedPath.includes('.')
|
|
133
|
+
? `.${requestedPath.split('.').pop() || ''}`.replace(/\.\./g, '.')
|
|
134
|
+
: undefined;
|
|
135
|
+
const sourcePrefix = requestedPath.includes('/')
|
|
136
|
+
? requestedPath.split('/').slice(0, -1).join('/')
|
|
137
|
+
: undefined;
|
|
138
|
+
const candidates = findFilesInArchive(archive, {
|
|
139
|
+
extension,
|
|
140
|
+
pathPrefix: sourcePrefix,
|
|
141
|
+
maxResults: 500,
|
|
142
|
+
});
|
|
143
|
+
const ranked = candidates
|
|
144
|
+
.map(candidate => ({
|
|
145
|
+
path: candidate,
|
|
146
|
+
distance: levenshtein(requestedPath.toLowerCase(), candidate.toLowerCase()),
|
|
147
|
+
}))
|
|
148
|
+
.filter(candidate => candidate.distance <= Math.max(3, Math.floor(requestedPath.length * 0.2)))
|
|
149
|
+
.sort((a, b) => a.distance - b.distance || a.path.localeCompare(b.path))
|
|
150
|
+
.slice(0, 5)
|
|
151
|
+
.map(candidate => candidate.path);
|
|
152
|
+
return ranked;
|
|
153
|
+
}
|
|
154
|
+
function levenshtein(a, b) {
|
|
155
|
+
if (a === b)
|
|
156
|
+
return 0;
|
|
157
|
+
if (a.length === 0)
|
|
158
|
+
return b.length;
|
|
159
|
+
if (b.length === 0)
|
|
160
|
+
return a.length;
|
|
161
|
+
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
162
|
+
const next = new Array(b.length + 1);
|
|
163
|
+
for (let i = 0; i < a.length; i++) {
|
|
164
|
+
next[0] = i + 1;
|
|
165
|
+
for (let j = 0; j < b.length; j++) {
|
|
166
|
+
const cost = a[i] === b[j] ? 0 : 1;
|
|
167
|
+
next[j + 1] = Math.min(next[j] + 1, prev[j + 1] + 1, prev[j] + cost);
|
|
168
|
+
}
|
|
169
|
+
for (let j = 0; j < next.length; j++) {
|
|
170
|
+
prev[j] = next[j];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return prev[b.length];
|
|
83
174
|
}
|
|
84
175
|
export { getMneFile as handler };
|
|
85
176
|
//# sourceMappingURL=getMneFile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMneFile.js","sourceRoot":"","sources":["../../src/tools/getMneFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"getMneFile.js","sourceRoot":"","sources":["../../src/tools/getMneFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,47 +1,18 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ToolContext } from '../types.js';
|
|
3
|
+
import { ForumTopicResult } from '../forum/client.js';
|
|
3
4
|
export declare const definition: {
|
|
4
|
-
name: string;
|
|
5
|
-
title: string;
|
|
6
|
-
description: string;
|
|
7
5
|
inputSchema: {
|
|
8
6
|
topicId: z.ZodNumber;
|
|
9
|
-
maxPosts: z.ZodOptional<z.ZodNumber
|
|
10
|
-
maxContentLength: z.ZodOptional<z.ZodNumber
|
|
7
|
+
maxPosts: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
8
|
+
maxContentLength: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
9
|
};
|
|
12
|
-
|
|
13
|
-
readonly readOnlyHint: true;
|
|
14
|
-
readonly destructiveHint: false;
|
|
15
|
-
readonly idempotentHint: true;
|
|
16
|
-
readonly openWorldHint: true;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* A single post within a forum topic.
|
|
21
|
-
*/
|
|
22
|
-
export interface ForumPost {
|
|
23
|
-
postNumber: number;
|
|
24
|
-
author: string;
|
|
25
|
-
content: string;
|
|
26
|
-
contentTruncated: boolean;
|
|
27
|
-
createdAt: string;
|
|
28
|
-
isAcceptedAnswer: boolean;
|
|
29
|
-
likeCount: number;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Full forum topic with all posts.
|
|
33
|
-
*/
|
|
34
|
-
export interface ForumTopicResult {
|
|
35
|
-
id: number;
|
|
10
|
+
name: string;
|
|
36
11
|
title: string;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
likeCount: number;
|
|
42
|
-
posts: ForumPost[];
|
|
43
|
-
totalPosts: number;
|
|
44
|
-
}
|
|
12
|
+
description: string;
|
|
13
|
+
annotations?: object;
|
|
14
|
+
outputSchema?: z.ZodTypeAny;
|
|
15
|
+
};
|
|
45
16
|
/**
|
|
46
17
|
* Fetches a full forum topic with all posts from the MNE Discourse forum.
|
|
47
18
|
* Use this after search_mne_forum to get complete discussion content.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMneForumTopic.d.ts","sourceRoot":"","sources":["../../src/tools/getMneForumTopic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"getMneForumTopic.d.ts","sourceRoot":"","sources":["../../src/tools/getMneForumTopic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAUtD,eAAO,MAAM,UAAU;;;;;;;;;;;CAMrB,CAAC;AAEH;;;GAGG;AACH,wBAAsB,gBAAgB,CAClC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,WAAW,GACrB,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,OAAO,EAAE,gBAAgB,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -1,149 +1,25 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { McpError } from '../types.js';
|
|
3
|
-
import { getLogger } from '../utils/logger.js';
|
|
4
2
|
import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
5
|
-
|
|
3
|
+
import { defineTool } from './defineTool.js';
|
|
6
4
|
const GetMneForumTopicParamsSchema = z.object({
|
|
7
|
-
topicId: z.number().int().positive('Topic ID must be a positive integer'),
|
|
8
|
-
maxPosts: z.number().int().min(1).max(100).optional().default(20),
|
|
9
|
-
maxContentLength: z.number().int().min(100).max(10000).optional().default(2000),
|
|
5
|
+
topicId: z.number().int().positive('Topic ID must be a positive integer').describe('Forum topic ID (from search_mne_forum results URL)'),
|
|
6
|
+
maxPosts: z.number().int().min(1).max(100).optional().default(20).describe('Max posts to return (default: 20)'),
|
|
7
|
+
maxContentLength: z.number().int().min(100).max(10000).optional().default(2000).describe('Truncate each post to N chars (default: 2000)'),
|
|
10
8
|
});
|
|
11
|
-
export const definition = {
|
|
9
|
+
export const definition = defineTool({
|
|
12
10
|
name: 'get_mne_forum_topic',
|
|
13
11
|
title: 'Get MNE Forum Topic',
|
|
14
12
|
description: 'Get the full content of a forum discussion including all posts. Use after search_mne_forum to read complete answers and solutions.',
|
|
15
|
-
|
|
16
|
-
topicId: z.number().int().positive().describe('Forum topic ID (from search_mne_forum results URL)'),
|
|
17
|
-
maxPosts: z.number().int().min(1).max(100).optional().describe('Max posts to return (default: 20)'),
|
|
18
|
-
maxContentLength: z.number().int().min(100).max(10000).optional().describe('Truncate each post to N chars (default: 2000)'),
|
|
19
|
-
},
|
|
13
|
+
paramsSchema: GetMneForumTopicParamsSchema,
|
|
20
14
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
21
|
-
};
|
|
15
|
+
});
|
|
22
16
|
/**
|
|
23
17
|
* Fetches a full forum topic with all posts from the MNE Discourse forum.
|
|
24
18
|
* Use this after search_mne_forum to get complete discussion content.
|
|
25
19
|
*/
|
|
26
20
|
export async function getMneForumTopic(params, context) {
|
|
27
21
|
const { topicId, maxPosts, maxContentLength } = GetMneForumTopicParamsSchema.parse(params);
|
|
28
|
-
|
|
29
|
-
const timeout = context.forum.timeout;
|
|
30
|
-
const url = `${baseUrl}/t/${topicId}.json`;
|
|
31
|
-
logger.debug(`Fetching forum topic: ${topicId}`);
|
|
32
|
-
try {
|
|
33
|
-
const response = await fetch(url, {
|
|
34
|
-
headers: { 'Accept': 'application/json' },
|
|
35
|
-
signal: AbortSignal.timeout(timeout || 15000),
|
|
36
|
-
});
|
|
37
|
-
if (!response.ok) {
|
|
38
|
-
if (response.status === 404) {
|
|
39
|
-
throw new McpError('FORUM_API_ERROR', `Forum topic not found: ${topicId}`, {
|
|
40
|
-
suggestion: 'Check the topic ID from search_mne_forum results',
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
throw new McpError('FORUM_API_ERROR', `Forum API error: ${response.status}`, {
|
|
44
|
-
details: response.statusText,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
const data = await response.json();
|
|
48
|
-
// Extract posts with content
|
|
49
|
-
const posts = data.post_stream.posts
|
|
50
|
-
.slice(0, maxPosts)
|
|
51
|
-
.map((p) => {
|
|
52
|
-
const fullContent = stripHtmlToMarkdown(p.cooked);
|
|
53
|
-
const truncated = fullContent.length > maxContentLength;
|
|
54
|
-
return {
|
|
55
|
-
postNumber: p.post_number,
|
|
56
|
-
author: p.username,
|
|
57
|
-
content: truncated
|
|
58
|
-
? fullContent.slice(0, maxContentLength) + '...'
|
|
59
|
-
: fullContent,
|
|
60
|
-
contentTruncated: truncated,
|
|
61
|
-
createdAt: p.created_at,
|
|
62
|
-
isAcceptedAnswer: p.accepted_answer || false,
|
|
63
|
-
likeCount: p.like_count || 0,
|
|
64
|
-
};
|
|
65
|
-
});
|
|
66
|
-
return {
|
|
67
|
-
id: data.id,
|
|
68
|
-
title: data.fancy_title || data.title,
|
|
69
|
-
url: `${baseUrl}/t/${data.slug}/${data.id}`,
|
|
70
|
-
category: getCategoryName(data.category_id),
|
|
71
|
-
tags: data.tags || [],
|
|
72
|
-
viewCount: data.views,
|
|
73
|
-
likeCount: data.like_count,
|
|
74
|
-
posts,
|
|
75
|
-
totalPosts: data.posts_count,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
if (error instanceof McpError)
|
|
80
|
-
throw error;
|
|
81
|
-
logger.error('Forum topic fetch error', { error, topicId });
|
|
82
|
-
throw new McpError('FORUM_API_ERROR', `Failed to fetch forum topic: ${topicId}`, {
|
|
83
|
-
details: error instanceof Error ? error.message : String(error),
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Convert HTML content to readable markdown.
|
|
89
|
-
*/
|
|
90
|
-
function stripHtmlToMarkdown(html) {
|
|
91
|
-
return html
|
|
92
|
-
// Code blocks
|
|
93
|
-
.replace(/<pre><code[^>]*>([\s\S]*?)<\/code><\/pre>/g, '\n```\n$1\n```\n')
|
|
94
|
-
// Inline code
|
|
95
|
-
.replace(/<code>([^<]+)<\/code>/g, '`$1`')
|
|
96
|
-
// Links
|
|
97
|
-
.replace(/<a href="([^"]+)"[^>]*>([^<]+)<\/a>/g, '[$2]($1)')
|
|
98
|
-
// Bold
|
|
99
|
-
.replace(/<strong>([^<]+)<\/strong>/g, '**$1**')
|
|
100
|
-
.replace(/<b>([^<]+)<\/b>/g, '**$1**')
|
|
101
|
-
// Italic
|
|
102
|
-
.replace(/<em>([^<]+)<\/em>/g, '*$1*')
|
|
103
|
-
.replace(/<i>([^<]+)<\/i>/g, '*$1*')
|
|
104
|
-
// Lists
|
|
105
|
-
.replace(/<li>/g, '- ')
|
|
106
|
-
.replace(/<\/li>/g, '\n')
|
|
107
|
-
.replace(/<\/?[uo]l>/g, '\n')
|
|
108
|
-
// Paragraphs and breaks
|
|
109
|
-
.replace(/<\/p>/g, '\n\n')
|
|
110
|
-
.replace(/<br\s*\/?>/g, '\n')
|
|
111
|
-
// Blockquotes
|
|
112
|
-
.replace(/<blockquote>([\s\S]*?)<\/blockquote>/g, (_, content) => content.split('\n').map((line) => `> ${line}`).join('\n'))
|
|
113
|
-
// Strip remaining tags
|
|
114
|
-
.replace(/<[^>]+>/g, '')
|
|
115
|
-
// HTML entities - named
|
|
116
|
-
.replace(/</g, '<')
|
|
117
|
-
.replace(/>/g, '>')
|
|
118
|
-
.replace(/&/g, '&')
|
|
119
|
-
.replace(/"/g, '"')
|
|
120
|
-
.replace(/'/g, "'")
|
|
121
|
-
.replace(/ /g, ' ')
|
|
122
|
-
.replace(/—/g, '—')
|
|
123
|
-
.replace(/–/g, '–')
|
|
124
|
-
.replace(/…/g, '…')
|
|
125
|
-
.replace(/©/g, '©')
|
|
126
|
-
.replace(/®/g, '®')
|
|
127
|
-
// HTML entities - numeric (decimal and hex)
|
|
128
|
-
.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10)))
|
|
129
|
-
.replace(/&#x([0-9a-fA-F]+);/g, (_, code) => String.fromCharCode(parseInt(code, 16)))
|
|
130
|
-
// Clean up whitespace
|
|
131
|
-
.replace(/\n{3,}/g, '\n\n')
|
|
132
|
-
.trim();
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Map category IDs to names (common MNE forum categories).
|
|
136
|
-
* Falls back to generic name if category ID is unknown.
|
|
137
|
-
*/
|
|
138
|
-
function getCategoryName(categoryId) {
|
|
139
|
-
const categories = {
|
|
140
|
-
1: 'General',
|
|
141
|
-
4: 'Usage Questions',
|
|
142
|
-
5: 'Development',
|
|
143
|
-
6: 'Announcements',
|
|
144
|
-
7: 'Showcase',
|
|
145
|
-
};
|
|
146
|
-
return categories[categoryId] || `Category ${categoryId}`;
|
|
22
|
+
return context.forum.getTopic(topicId, { maxPosts, maxContentLength });
|
|
147
23
|
}
|
|
148
24
|
export { getMneForumTopic as handler };
|
|
149
25
|
//# sourceMappingURL=getMneForumTopic.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMneForumTopic.js","sourceRoot":"","sources":["../../src/tools/getMneForumTopic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"getMneForumTopic.js","sourceRoot":"","sources":["../../src/tools/getMneForumTopic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC,CAAC,QAAQ,CAAC,oDAAoD,CAAC;IACxI,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IAC/G,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,+CAA+C,CAAC;CAC5I,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;IACjC,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,qBAAqB;IAC5B,WAAW,EAAE,oIAAoI;IACjJ,YAAY,EAAE,4BAA4B;IAC1C,WAAW,EAAE,0BAA0B;CAC1C,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,MAAe,EACf,OAAoB;IAEpB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,4BAA4B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3F,OAAO,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,OAAO,EAAE,gBAAgB,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ToolContext } from '../types.js';
|
|
2
|
+
import { RequestBudgetSummary, ToolContext } from '../types.js';
|
|
3
3
|
import { GitHubIssueDetail } from '../github/types.js';
|
|
4
4
|
export declare const definition: {
|
|
5
|
-
name: string;
|
|
6
|
-
title: string;
|
|
7
|
-
description: string;
|
|
8
5
|
inputSchema: {
|
|
9
6
|
issueNumber: z.ZodNumber;
|
|
7
|
+
brief: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
10
8
|
package: z.ZodOptional<z.ZodEnum<[string, ...string[]]>>;
|
|
11
9
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
10
|
+
name: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
annotations?: object;
|
|
14
|
+
outputSchema?: z.ZodTypeAny;
|
|
18
15
|
};
|
|
19
16
|
export interface GetMneIssueResult extends GitHubIssueDetail {
|
|
20
17
|
package: string;
|
|
18
|
+
requestBudget?: RequestBudgetSummary;
|
|
21
19
|
}
|
|
22
20
|
export declare function getMneIssue(params: unknown, context: ToolContext): Promise<GetMneIssueResult>;
|
|
23
21
|
export { getMneIssue as handler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMneIssue.d.ts","sourceRoot":"","sources":["../../src/tools/getMneIssue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAY,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"getMneIssue.d.ts","sourceRoot":"","sources":["../../src/tools/getMneIssue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAY,oBAAoB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAYvD,eAAO,MAAM,UAAU;;;;;;;;;;;CAMrB,CAAC;AAEH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACxC;AAED,wBAAsB,WAAW,CAC7B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,WAAW,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,OAAO,EAAE,WAAW,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { McpError } from '../types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { packageSchema } from '../config.js';
|
|
4
4
|
import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
5
|
+
import { defineTool } from './defineTool.js';
|
|
6
|
+
import { buildGithubRequestBudget } from './requestBudget.js';
|
|
5
7
|
const GetMneIssueParamsSchema = z.object({
|
|
6
|
-
issueNumber: z.number().int().positive('Issue number must be a positive integer'),
|
|
7
|
-
|
|
8
|
+
issueNumber: z.number().int().positive('Issue number must be a positive integer').describe('GitHub issue number, e.g. 12345'),
|
|
9
|
+
brief: z.boolean().optional().default(false).describe('Return a shorter body preview (default: false)'),
|
|
10
|
+
package: packageSchema,
|
|
8
11
|
});
|
|
9
|
-
export const definition = {
|
|
12
|
+
export const definition = defineTool({
|
|
10
13
|
name: 'get_mne_issue',
|
|
11
14
|
title: 'Get MNE Issue',
|
|
12
15
|
description: 'Get full details of a specific GitHub issue by number. Use after search_mne_issues to read the complete issue description and context.',
|
|
13
|
-
|
|
14
|
-
issueNumber: z.number().int().positive().describe('GitHub issue number, e.g. 12345'),
|
|
15
|
-
package: packageSchema,
|
|
16
|
-
},
|
|
16
|
+
paramsSchema: GetMneIssueParamsSchema,
|
|
17
17
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
18
|
-
};
|
|
18
|
+
});
|
|
19
19
|
export async function getMneIssue(params, context) {
|
|
20
|
-
const { issueNumber, package: packageName } = GetMneIssueParamsSchema.parse(params);
|
|
20
|
+
const { issueNumber, brief, package: packageName } = GetMneIssueParamsSchema.parse(params);
|
|
21
21
|
const issue = await context.github.getIssue(issueNumber, packageName);
|
|
22
22
|
if (!issue) {
|
|
23
23
|
throw new McpError('ISSUE_NOT_FOUND', `Issue #${issueNumber} not found`, {
|
|
@@ -25,9 +25,15 @@ export async function getMneIssue(params, context) {
|
|
|
25
25
|
suggestion: 'Use search_mne_issues to find valid issue numbers.',
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
+
const maxBodyLength = 400;
|
|
29
|
+
const bodyTruncated = brief && issue.body.length > maxBodyLength;
|
|
28
30
|
return {
|
|
29
31
|
...issue,
|
|
32
|
+
type: issue.type || 'issue',
|
|
33
|
+
body: bodyTruncated ? `${issue.body.slice(0, maxBodyLength)}...` : issue.body,
|
|
34
|
+
bodyTruncated,
|
|
30
35
|
package: packageName || 'mne-python',
|
|
36
|
+
requestBudget: buildGithubRequestBudget(context.github, ['core']),
|
|
31
37
|
};
|
|
32
38
|
}
|
|
33
39
|
export { getMneIssue as handler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMneIssue.js","sourceRoot":"","sources":["../../src/tools/getMneIssue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"getMneIssue.js","sourceRoot":"","sources":["../../src/tools/getMneIssue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAqC,MAAM,aAAa,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC7H,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,gDAAgD,CAAC;IACvG,OAAO,EAAE,aAAa;CACzB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;IACjC,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,eAAe;IACtB,WAAW,EAAE,wIAAwI;IACrJ,YAAY,EAAE,uBAAuB;IACrC,WAAW,EAAE,0BAA0B;CAC1C,CAAC,CAAC;AAOH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC7B,MAAe,EACf,OAAoB;IAEpB,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3F,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAEtE,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,UAAU,WAAW,YAAY,EAAE;YACrE,OAAO,EAAE,YAAY,WAAW,IAAI,YAAY,EAAE;YAClD,UAAU,EAAE,oDAAoD;SACnE,CAAC,CAAC;IACP,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,CAAC;IAC1B,MAAM,aAAa,GAAG,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC;IAEjE,OAAO;QACH,GAAG,KAAK;QACR,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;QAC3B,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;QAC7E,aAAa;QACb,OAAO,EAAE,WAAW,IAAI,YAAY;QACpC,aAAa,EAAE,wBAAwB,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;KACpE,CAAC;AACN,CAAC;AAED,OAAO,EAAE,WAAW,IAAI,OAAO,EAAE,CAAC"}
|