ms-vite-plugin 1.4.16 → 1.4.17
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/cli.js +6 -301
- package/dist/mcp/doc-tools.js +1 -119
- package/dist/mcp/docs-service.d.ts +1 -27
- package/dist/mcp/docs-service.js +0 -65
- package/dist/mcp/httpapi-docs-service.d.ts +4 -37
- package/dist/mcp/httpapi-docs-service.js +6 -83
- package/dist/mcp/httpapi-tools.d.ts +1 -1
- package/dist/mcp/httpapi-tools.js +7 -157
- package/dist/mcp/tool-utils.d.ts +0 -13
- package/dist/mcp/tool-utils.js +0 -21
- package/dist/mcp/types.d.ts +0 -13
- package/docs/AGENTS.md +23 -31
- package/docs/SKILL.md +26 -37
- package/docs/mcp-agent-description.md +32 -58
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -148,16 +148,6 @@ function parseCliChoice(value, defaultValue, choices, name) {
|
|
|
148
148
|
}
|
|
149
149
|
return text;
|
|
150
150
|
}
|
|
151
|
-
/**
|
|
152
|
-
* 解析文档语言参数
|
|
153
|
-
* @param value 用户传入的语言
|
|
154
|
-
* @returns 返回文档语言
|
|
155
|
-
* @example
|
|
156
|
-
* parseDocsLanguageOption("js_zh")
|
|
157
|
-
*/
|
|
158
|
-
function parseDocsLanguageOption(value) {
|
|
159
|
-
return parseCliChoice(value, "js_zh", ["js", "js_zh", "python"], "language");
|
|
160
|
-
}
|
|
161
151
|
/**
|
|
162
152
|
* 解析 HTTP API 请求方法
|
|
163
153
|
* @param value 用户传入的方法
|
|
@@ -169,19 +159,6 @@ function parseHttpApiMethodOption(value) {
|
|
|
169
159
|
const method = value?.trim().toUpperCase();
|
|
170
160
|
return parseCliChoice(method, "GET", ["GET", "POST"], "method");
|
|
171
161
|
}
|
|
172
|
-
/**
|
|
173
|
-
* 解析可选 HTTP API 请求方法
|
|
174
|
-
* @param value 用户传入的方法
|
|
175
|
-
* @returns 返回 HTTP API 方法或 undefined
|
|
176
|
-
* @example
|
|
177
|
-
* parseOptionalHttpApiMethodOption("POST")
|
|
178
|
-
*/
|
|
179
|
-
function parseOptionalHttpApiMethodOption(value) {
|
|
180
|
-
if (!value?.trim()) {
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
return parseHttpApiMethodOption(value);
|
|
184
|
-
}
|
|
185
162
|
/**
|
|
186
163
|
* 解析设备 HTTP 地址
|
|
187
164
|
* @param options 设备命令选项
|
|
@@ -220,44 +197,6 @@ async function writeOrPrintText(text, output, savedLabel) {
|
|
|
220
197
|
}
|
|
221
198
|
console.log(text);
|
|
222
199
|
}
|
|
223
|
-
/**
|
|
224
|
-
* 格式化 API 文档摘要
|
|
225
|
-
* @param language 文档语言
|
|
226
|
-
* @param title 文档标题
|
|
227
|
-
* @param slug 文档 slug
|
|
228
|
-
* @param index 序号
|
|
229
|
-
* @param filePath 文档文件绝对路径
|
|
230
|
-
* @returns 返回摘要文本
|
|
231
|
-
* @example
|
|
232
|
-
* formatCliApiDocSummary("js_zh", "设备", "device", 0, "/tmp/device.md")
|
|
233
|
-
*/
|
|
234
|
-
function formatCliApiDocSummary(language, title, slug, index, filePath) {
|
|
235
|
-
return [
|
|
236
|
-
`${index + 1}. ${title}`,
|
|
237
|
-
`slug: ${slug}`,
|
|
238
|
-
`uri: ${(0, docs_service_1.getDocUri)(language, slug)}`,
|
|
239
|
-
...(filePath ? [`path: ${filePath}`] : []),
|
|
240
|
-
].join("\n");
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* 格式化 HTTP API 文档摘要
|
|
244
|
-
* @param entry HTTP API 文档条目
|
|
245
|
-
* @param index 序号
|
|
246
|
-
* @returns 返回摘要文本
|
|
247
|
-
* @example
|
|
248
|
-
* formatCliHttpApiDocSummary(entry, 0)
|
|
249
|
-
*/
|
|
250
|
-
function formatCliHttpApiDocSummary(entry, index) {
|
|
251
|
-
return [
|
|
252
|
-
`${index + 1}. ${entry.title}`,
|
|
253
|
-
`method: ${entry.method}`,
|
|
254
|
-
`path: ${entry.path}`,
|
|
255
|
-
`slug: ${entry.slug}`,
|
|
256
|
-
`section: ${entry.section || "未分组"}`,
|
|
257
|
-
`lines: ${entry.startLine}-${entry.endLine}`,
|
|
258
|
-
`file: ${entry.filePath}`,
|
|
259
|
-
].join("\n");
|
|
260
|
-
}
|
|
261
200
|
/**
|
|
262
201
|
* 格式化 CLI 文档路径清单
|
|
263
202
|
* @returns 返回本地文档路径文本
|
|
@@ -271,7 +210,7 @@ function formatCliDocsPathsText() {
|
|
|
271
210
|
`docsRoot: ${(0, docs_service_1.getDocsRootDir)()}`,
|
|
272
211
|
...languages.map((language) => `${language}: ${(0, docs_service_1.getDocsDirByLanguage)(language)} (${types_1.DOC_LANGUAGE_LABELS[language]})`),
|
|
273
212
|
`httpApi: ${(0, httpapi_docs_service_1.getHttpApiDocPath)()}`,
|
|
274
|
-
"说明: 直接读取上述 markdown
|
|
213
|
+
"说明: 直接读取上述 markdown 路径。",
|
|
275
214
|
].join("\n");
|
|
276
215
|
}
|
|
277
216
|
/**
|
|
@@ -642,30 +581,6 @@ async function logsCommand(options) {
|
|
|
642
581
|
process.exit(1);
|
|
643
582
|
}
|
|
644
583
|
}
|
|
645
|
-
/**
|
|
646
|
-
* docs list 命令处理函数
|
|
647
|
-
* @param options 命令选项
|
|
648
|
-
* @returns 请求完成后退出
|
|
649
|
-
* @example
|
|
650
|
-
* ms docs list --language js_zh
|
|
651
|
-
*/
|
|
652
|
-
async function docsListCommand(options) {
|
|
653
|
-
try {
|
|
654
|
-
const language = parseDocsLanguageOption(options.language);
|
|
655
|
-
const docs = await (0, docs_service_1.getApiDocsByLanguage)(language);
|
|
656
|
-
const lines = docs.map((doc, index) => formatCliApiDocSummary(language, doc.title, doc.slug, index, doc.filePath));
|
|
657
|
-
const text = [
|
|
658
|
-
`文档语言: ${language} (${types_1.DOC_LANGUAGE_LABELS[language]})`,
|
|
659
|
-
"",
|
|
660
|
-
...(lines.length > 0 ? lines : ["无可用文档"]),
|
|
661
|
-
].join("\n");
|
|
662
|
-
await writeOrPrintText(text, options.output, "文档列表已保存");
|
|
663
|
-
}
|
|
664
|
-
catch (error) {
|
|
665
|
-
console.error("❌ 列出文档失败:", error instanceof Error ? error.message : error);
|
|
666
|
-
process.exit(1);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
584
|
/**
|
|
670
585
|
* docs paths 命令处理函数
|
|
671
586
|
* @param options 命令选项
|
|
@@ -682,186 +597,21 @@ async function docsPathsCommand(options) {
|
|
|
682
597
|
process.exit(1);
|
|
683
598
|
}
|
|
684
599
|
}
|
|
685
|
-
/**
|
|
686
|
-
* docs search 命令处理函数
|
|
687
|
-
* @param query 搜索词
|
|
688
|
-
* @param options 命令选项
|
|
689
|
-
* @returns 请求完成后退出
|
|
690
|
-
* @example
|
|
691
|
-
* ms docs search 点击 --language js_zh --limit 5
|
|
692
|
-
*/
|
|
693
|
-
async function docsSearchCommand(query, options) {
|
|
694
|
-
try {
|
|
695
|
-
const language = parseDocsLanguageOption(options.language);
|
|
696
|
-
const limit = parseCliInteger(options.limit, 5, "limit", 1, 20);
|
|
697
|
-
const normalizedQuery = query.toLowerCase();
|
|
698
|
-
const docs = await (0, docs_service_1.getApiDocsByLanguage)(language);
|
|
699
|
-
const matches = docs
|
|
700
|
-
.map((doc) => ({ doc, score: (0, docs_service_1.scoreApiDoc)(doc, normalizedQuery) }))
|
|
701
|
-
.filter((item) => item.score > 0)
|
|
702
|
-
.sort((a, b) => b.score - a.score || a.doc.slug.localeCompare(b.doc.slug))
|
|
703
|
-
.slice(0, limit)
|
|
704
|
-
.map((item) => item.doc);
|
|
705
|
-
const text = matches.length === 0
|
|
706
|
-
? `文档语言: ${language} (${types_1.DOC_LANGUAGE_LABELS[language]})\n未找到与 "${query}" 匹配的文档。`
|
|
707
|
-
: [
|
|
708
|
-
`文档语言: ${language} (${types_1.DOC_LANGUAGE_LABELS[language]})`,
|
|
709
|
-
"",
|
|
710
|
-
...matches.map((doc, index) => formatCliApiDocSummary(language, doc.title, doc.slug, index, doc.filePath)),
|
|
711
|
-
].join("\n");
|
|
712
|
-
await writeOrPrintText(text, options.output, "文档搜索结果已保存");
|
|
713
|
-
}
|
|
714
|
-
catch (error) {
|
|
715
|
-
console.error("❌ 搜索文档失败:", error instanceof Error ? error.message : error);
|
|
716
|
-
process.exit(1);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
/**
|
|
720
|
-
* docs read 命令处理函数
|
|
721
|
-
* @param slug 文档 slug
|
|
722
|
-
* @param options 命令选项
|
|
723
|
-
* @returns 请求完成后退出
|
|
724
|
-
* @example
|
|
725
|
-
* ms docs read action --language js_zh
|
|
726
|
-
*/
|
|
727
|
-
async function docsReadCommand(slug, options) {
|
|
728
|
-
try {
|
|
729
|
-
const language = parseDocsLanguageOption(options.language);
|
|
730
|
-
const docs = await (0, docs_service_1.getApiDocsByLanguage)(language);
|
|
731
|
-
const target = docs.find((doc) => doc.slug === slug);
|
|
732
|
-
if (!target) {
|
|
733
|
-
throw new Error(`未找到文档 ${slug}.md(语言: ${language})。`);
|
|
734
|
-
}
|
|
735
|
-
const text = [
|
|
736
|
-
`标题: ${target.title}`,
|
|
737
|
-
`语言: ${language}`,
|
|
738
|
-
`URI: ${(0, docs_service_1.getDocUri)(language, target.slug)}`,
|
|
739
|
-
`path: ${target.filePath}`,
|
|
740
|
-
"",
|
|
741
|
-
target.content,
|
|
742
|
-
].join("\n");
|
|
743
|
-
await writeOrPrintText(text, options.output, "文档已保存");
|
|
744
|
-
}
|
|
745
|
-
catch (error) {
|
|
746
|
-
console.error("❌ 读取文档失败:", error instanceof Error ? error.message : error);
|
|
747
|
-
process.exit(1);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* http-docs list 命令处理函数
|
|
752
|
-
* @param options 命令选项
|
|
753
|
-
* @returns 请求完成后退出
|
|
754
|
-
* @example
|
|
755
|
-
* ms http-docs list
|
|
756
|
-
*/
|
|
757
|
-
async function httpDocsListCommand(options) {
|
|
758
|
-
try {
|
|
759
|
-
const entries = await (0, httpapi_docs_service_1.getHttpApiDocEntries)();
|
|
760
|
-
const text = [
|
|
761
|
-
"HTTP API 文档列表:",
|
|
762
|
-
"",
|
|
763
|
-
...entries.map((entry, index) => formatCliHttpApiDocSummary(entry, index)),
|
|
764
|
-
].join("\n");
|
|
765
|
-
await writeOrPrintText(text, options.output, "HTTP API 文档列表已保存");
|
|
766
|
-
}
|
|
767
|
-
catch (error) {
|
|
768
|
-
console.error("❌ 列出 HTTP API 文档失败:", error instanceof Error ? error.message : error);
|
|
769
|
-
process.exit(1);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* http-docs search 命令处理函数
|
|
774
|
-
* @param query 搜索词
|
|
775
|
-
* @param options 命令选项
|
|
776
|
-
* @returns 请求完成后退出
|
|
777
|
-
* @example
|
|
778
|
-
* ms http-docs search 截图 --limit 8
|
|
779
|
-
*/
|
|
780
|
-
async function httpDocsSearchCommand(query, options) {
|
|
781
|
-
try {
|
|
782
|
-
const limit = parseCliInteger(options.limit, 8, "limit", 1, 20);
|
|
783
|
-
const normalizedQuery = query.toLowerCase();
|
|
784
|
-
const entries = await (0, httpapi_docs_service_1.getHttpApiDocEntries)();
|
|
785
|
-
const matches = entries
|
|
786
|
-
.map((entry) => ({
|
|
787
|
-
entry,
|
|
788
|
-
score: (0, httpapi_docs_service_1.scoreHttpApiDocEntry)(entry, normalizedQuery),
|
|
789
|
-
}))
|
|
790
|
-
.filter((item) => item.score > 0)
|
|
791
|
-
.sort((a, b) => b.score - a.score ||
|
|
792
|
-
a.entry.path.localeCompare(b.entry.path) ||
|
|
793
|
-
a.entry.method.localeCompare(b.entry.method))
|
|
794
|
-
.slice(0, limit)
|
|
795
|
-
.map((item) => item.entry);
|
|
796
|
-
const text = matches.length === 0
|
|
797
|
-
? `未找到与 "${query}" 匹配的 HTTP API 文档。`
|
|
798
|
-
: [
|
|
799
|
-
"HTTP API 文档匹配结果:",
|
|
800
|
-
"",
|
|
801
|
-
...matches.map((entry, index) => formatCliHttpApiDocSummary(entry, index)),
|
|
802
|
-
].join("\n");
|
|
803
|
-
await writeOrPrintText(text, options.output, "HTTP API 文档搜索结果已保存");
|
|
804
|
-
}
|
|
805
|
-
catch (error) {
|
|
806
|
-
console.error("❌ 搜索 HTTP API 文档失败:", error instanceof Error ? error.message : error);
|
|
807
|
-
process.exit(1);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
/**
|
|
811
|
-
* http-docs read 命令处理函数
|
|
812
|
-
* @param identifier slug 或接口路径
|
|
813
|
-
* @param options 命令选项
|
|
814
|
-
* @returns 请求完成后退出
|
|
815
|
-
* @example
|
|
816
|
-
* ms http-docs read /api/source --method GET
|
|
817
|
-
*/
|
|
818
|
-
async function httpDocsReadCommand(identifier, options) {
|
|
819
|
-
try {
|
|
820
|
-
const method = parseOptionalHttpApiMethodOption(options.method);
|
|
821
|
-
const entry = await (0, httpapi_docs_service_1.findHttpApiDocEntry)(identifier, method);
|
|
822
|
-
if (!entry) {
|
|
823
|
-
throw new Error(`未找到 HTTP API 文档: ${identifier}`);
|
|
824
|
-
}
|
|
825
|
-
const text = [
|
|
826
|
-
`title: ${entry.title}`,
|
|
827
|
-
`method: ${entry.method}`,
|
|
828
|
-
`path: ${entry.path}`,
|
|
829
|
-
`slug: ${entry.slug}`,
|
|
830
|
-
`section: ${entry.section || "未分组"}`,
|
|
831
|
-
`lines: ${entry.startLine}-${entry.endLine}`,
|
|
832
|
-
`file: ${entry.filePath}`,
|
|
833
|
-
"",
|
|
834
|
-
entry.content,
|
|
835
|
-
].join("\n");
|
|
836
|
-
await writeOrPrintText(text, options.output, "HTTP API 文档已保存");
|
|
837
|
-
}
|
|
838
|
-
catch (error) {
|
|
839
|
-
console.error("❌ 读取 HTTP API 文档失败:", error instanceof Error ? error.message : error);
|
|
840
|
-
process.exit(1);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
600
|
/**
|
|
844
601
|
* http-call 命令处理函数
|
|
845
602
|
* @param options 命令选项
|
|
846
603
|
* @returns 请求完成后退出
|
|
847
604
|
* @example
|
|
848
|
-
* ms http-call --ip 192.168.1.100 --method GET --path /api/status
|
|
605
|
+
* ms http-call --ip 192.168.1.100 --method GET --path /api/status
|
|
849
606
|
*/
|
|
850
607
|
async function httpCallCommand(options) {
|
|
851
608
|
try {
|
|
852
609
|
const target = parseDeviceHttpTarget(options);
|
|
853
610
|
const method = parseHttpApiMethodOption(options.method);
|
|
854
611
|
const apiPath = normalizeCliHttpApiPath(options.path ?? "");
|
|
855
|
-
const
|
|
856
|
-
if (!docSlug) {
|
|
857
|
-
throw new Error("请通过 --doc-slug 指定 HTTP API 文档 slug。");
|
|
858
|
-
}
|
|
859
|
-
const entry = await (0, httpapi_docs_service_1.findHttpApiDocEntry)(docSlug);
|
|
612
|
+
const entry = await (0, httpapi_docs_service_1.findHttpApiDocEntry)(apiPath, method);
|
|
860
613
|
if (!entry) {
|
|
861
|
-
throw new Error(`HTTP API
|
|
862
|
-
}
|
|
863
|
-
if (entry.method !== method || entry.path !== apiPath) {
|
|
864
|
-
throw new Error(`HTTP API 调用与文档条目不匹配。传入 ${method} ${apiPath},文档 ${entry.method} ${entry.path}。`);
|
|
614
|
+
throw new Error(`HTTP API 文档中不存在该接口: ${method} ${apiPath}。请先读取 docs paths 返回的 HTTP API 文档路径。`);
|
|
865
615
|
}
|
|
866
616
|
const query = parseJsonRecordOption(options.query, "query");
|
|
867
617
|
const body = parseJsonBodyOption(options.body);
|
|
@@ -886,7 +636,7 @@ async function httpCallCommand(options) {
|
|
|
886
636
|
const text = [
|
|
887
637
|
`HTTP API 调用${response.ok ? "成功" : "失败"}: ${method} ${apiPath}`,
|
|
888
638
|
`设备: ${target.label}`,
|
|
889
|
-
`文档: ${entry.title} (
|
|
639
|
+
`文档: ${entry.title} (lines ${entry.startLine}-${entry.endLine})`,
|
|
890
640
|
`状态码: ${response.status}`,
|
|
891
641
|
"",
|
|
892
642
|
responseText,
|
|
@@ -1426,56 +1176,12 @@ commander_1.program
|
|
|
1426
1176
|
// API 文档命令
|
|
1427
1177
|
const docsCommand = commander_1.program
|
|
1428
1178
|
.command("docs")
|
|
1429
|
-
.description("
|
|
1179
|
+
.description("显示 KuaiJS 本地文档路径");
|
|
1430
1180
|
docsCommand
|
|
1431
1181
|
.command("paths")
|
|
1432
1182
|
.description("显示 KuaiJS 本地文档路径")
|
|
1433
1183
|
.option("--output <output>", "输出文件路径(可选)")
|
|
1434
1184
|
.action(docsPathsCommand);
|
|
1435
|
-
docsCommand
|
|
1436
|
-
.command("list")
|
|
1437
|
-
.description("列出 API 文档")
|
|
1438
|
-
.option("--language <language>", "文档语言: js|js_zh|python", "js_zh")
|
|
1439
|
-
.option("--output <output>", "输出文件路径(可选)")
|
|
1440
|
-
.action(docsListCommand);
|
|
1441
|
-
docsCommand
|
|
1442
|
-
.command("search")
|
|
1443
|
-
.description("搜索 API 文档")
|
|
1444
|
-
.argument("<query>", "搜索关键字")
|
|
1445
|
-
.option("--language <language>", "文档语言: js|js_zh|python", "js_zh")
|
|
1446
|
-
.option("--limit <limit>", "返回条数上限,范围 1..20", "5")
|
|
1447
|
-
.option("--output <output>", "输出文件路径(可选)")
|
|
1448
|
-
.action(docsSearchCommand);
|
|
1449
|
-
docsCommand
|
|
1450
|
-
.command("read")
|
|
1451
|
-
.description("读取 API 文档")
|
|
1452
|
-
.argument("<slug>", "文档 slug(文件名,不含 .md)")
|
|
1453
|
-
.option("--language <language>", "文档语言: js|js_zh|python", "js_zh")
|
|
1454
|
-
.option("--output <output>", "输出文件路径(可选)")
|
|
1455
|
-
.action(docsReadCommand);
|
|
1456
|
-
// HTTP API 文档命令
|
|
1457
|
-
const httpDocsCommand = commander_1.program
|
|
1458
|
-
.command("http-docs")
|
|
1459
|
-
.description("查询 KuaiJS 设备 HTTP API 文档");
|
|
1460
|
-
httpDocsCommand
|
|
1461
|
-
.command("list")
|
|
1462
|
-
.description("列出 HTTP API 文档条目")
|
|
1463
|
-
.option("--output <output>", "输出文件路径(可选)")
|
|
1464
|
-
.action(httpDocsListCommand);
|
|
1465
|
-
httpDocsCommand
|
|
1466
|
-
.command("search")
|
|
1467
|
-
.description("搜索 HTTP API 文档")
|
|
1468
|
-
.argument("<query>", "搜索关键字、标题或接口路径")
|
|
1469
|
-
.option("--limit <limit>", "返回条数上限,范围 1..20", "8")
|
|
1470
|
-
.option("--output <output>", "输出文件路径(可选)")
|
|
1471
|
-
.action(httpDocsSearchCommand);
|
|
1472
|
-
httpDocsCommand
|
|
1473
|
-
.command("read")
|
|
1474
|
-
.description("读取 HTTP API 文档条目")
|
|
1475
|
-
.argument("<identifier>", "接口 slug 或 path")
|
|
1476
|
-
.option("--method <method>", "HTTP 方法,用于同路径多方法时消歧: GET|POST")
|
|
1477
|
-
.option("--output <output>", "输出文件路径(可选)")
|
|
1478
|
-
.action(httpDocsReadCommand);
|
|
1479
1185
|
// HTTP API 调用命令
|
|
1480
1186
|
commander_1.program
|
|
1481
1187
|
.command("http-call")
|
|
@@ -1484,7 +1190,6 @@ commander_1.program
|
|
|
1484
1190
|
.option("--port <port>", "设备端口", "9800")
|
|
1485
1191
|
.requiredOption("--method <method>", "HTTP 方法: GET|POST")
|
|
1486
1192
|
.requiredOption("--path <path>", "HTTP API 相对路径,例如 /api/status")
|
|
1487
|
-
.requiredOption("--doc-slug <docSlug>", "http-docs 返回的接口 slug")
|
|
1488
1193
|
.option("--query <query>", "JSON 对象 query 参数")
|
|
1489
1194
|
.option("--body <body>", "JSON 请求体;普通字符串会作为 JSON 字符串提交")
|
|
1490
1195
|
.option("--response-format <responseFormat>", "响应格式: json|text", "json")
|
package/dist/mcp/doc-tools.js
CHANGED
|
@@ -1,40 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.registerDocTools = registerDocTools;
|
|
37
|
-
const z = __importStar(require("zod/v4"));
|
|
38
4
|
const docs_service_1 = require("./docs-service");
|
|
39
5
|
const httpapi_docs_service_1 = require("./httpapi-docs-service");
|
|
40
6
|
const tool_utils_1 = require("./tool-utils");
|
|
@@ -52,7 +18,7 @@ function formatDocsPathsText() {
|
|
|
52
18
|
`docsRoot: ${(0, docs_service_1.getDocsRootDir)()}`,
|
|
53
19
|
...languages.map((language) => `${language}: ${(0, docs_service_1.getDocsDirByLanguage)(language)} (${types_1.DOC_LANGUAGE_LABELS[language]})`),
|
|
54
20
|
`httpApi: ${(0, httpapi_docs_service_1.getHttpApiDocPath)()}`,
|
|
55
|
-
"说明: 直接读取上述 markdown
|
|
21
|
+
"说明: 直接读取上述 markdown 路径。",
|
|
56
22
|
].join("\n");
|
|
57
23
|
}
|
|
58
24
|
/**
|
|
@@ -70,88 +36,4 @@ function registerDocTools(server) {
|
|
|
70
36
|
}, async () => {
|
|
71
37
|
return (0, tool_utils_1.createTextToolResult)(formatDocsPathsText());
|
|
72
38
|
});
|
|
73
|
-
server.registerTool("list_api_docs", {
|
|
74
|
-
title: "List API Docs",
|
|
75
|
-
description: "列出指定语言下可用的 API 文档;不传 language 时默认 js_zh。",
|
|
76
|
-
inputSchema: {
|
|
77
|
-
language: z
|
|
78
|
-
.enum(["js", "js_zh", "python"])
|
|
79
|
-
.optional()
|
|
80
|
-
.describe("可选语言,不传默认 js_zh"),
|
|
81
|
-
},
|
|
82
|
-
}, async ({ language }) => {
|
|
83
|
-
const activeLanguage = language ?? "js_zh";
|
|
84
|
-
const docs = await (0, docs_service_1.getApiDocsByLanguage)(activeLanguage);
|
|
85
|
-
const lines = docs.map((doc, index) => (0, tool_utils_1.formatApiDocSummary)(activeLanguage, doc.title, doc.slug, index, doc.filePath));
|
|
86
|
-
return (0, tool_utils_1.createTextToolResult)(lines.length === 0
|
|
87
|
-
? `文档语言 ${activeLanguage} 下没有可用文档。`
|
|
88
|
-
: [
|
|
89
|
-
`文档语言: ${activeLanguage} (${types_1.DOC_LANGUAGE_LABELS[activeLanguage]})`,
|
|
90
|
-
"",
|
|
91
|
-
...lines,
|
|
92
|
-
].join("\n"));
|
|
93
|
-
});
|
|
94
|
-
server.registerTool("search_api_docs", {
|
|
95
|
-
title: "Search API Docs",
|
|
96
|
-
description: "在指定语言文档中按关键字搜索;不传 language 时默认 js_zh。",
|
|
97
|
-
inputSchema: {
|
|
98
|
-
query: z.string().min(1).describe("搜索关键字"),
|
|
99
|
-
limit: z
|
|
100
|
-
.number()
|
|
101
|
-
.int()
|
|
102
|
-
.min(1)
|
|
103
|
-
.max(20)
|
|
104
|
-
.optional()
|
|
105
|
-
.default(5)
|
|
106
|
-
.describe("返回条数上限,默认 5"),
|
|
107
|
-
language: z
|
|
108
|
-
.enum(["js", "js_zh", "python"])
|
|
109
|
-
.optional()
|
|
110
|
-
.describe("可选语言,不传默认 js_zh"),
|
|
111
|
-
},
|
|
112
|
-
}, async ({ query, limit, language }) => {
|
|
113
|
-
const activeLanguage = language ?? "js_zh";
|
|
114
|
-
const docs = await (0, docs_service_1.getApiDocsByLanguage)(activeLanguage);
|
|
115
|
-
const normalizedQuery = query.toLowerCase();
|
|
116
|
-
const matches = docs
|
|
117
|
-
.map((doc) => ({ doc, score: (0, docs_service_1.scoreApiDoc)(doc, normalizedQuery) }))
|
|
118
|
-
.filter((item) => item.score > 0)
|
|
119
|
-
.sort((a, b) => b.score - a.score || a.doc.slug.localeCompare(b.doc.slug))
|
|
120
|
-
.slice(0, limit)
|
|
121
|
-
.map((item) => item.doc);
|
|
122
|
-
const text = matches.length === 0
|
|
123
|
-
? `文档语言: ${activeLanguage} (${types_1.DOC_LANGUAGE_LABELS[activeLanguage]})\n未找到与 "${query}" 匹配的文档。`
|
|
124
|
-
: [
|
|
125
|
-
`文档语言: ${activeLanguage} (${types_1.DOC_LANGUAGE_LABELS[activeLanguage]})`,
|
|
126
|
-
"",
|
|
127
|
-
...matches.map((doc, index) => (0, tool_utils_1.formatApiDocSummary)(activeLanguage, doc.title, doc.slug, index, doc.filePath)),
|
|
128
|
-
].join("\n");
|
|
129
|
-
return (0, tool_utils_1.createTextToolResult)(text);
|
|
130
|
-
});
|
|
131
|
-
server.registerTool("read_api_doc", {
|
|
132
|
-
title: "Read API Doc",
|
|
133
|
-
description: "读取指定语言下某个文档的完整 markdown 内容;不传 language 时默认 js_zh。",
|
|
134
|
-
inputSchema: {
|
|
135
|
-
slug: z.string().min(1).describe("文档 slug(文件名,不含 .md)"),
|
|
136
|
-
language: z
|
|
137
|
-
.enum(["js", "js_zh", "python"])
|
|
138
|
-
.optional()
|
|
139
|
-
.describe("可选语言,不传默认 js_zh"),
|
|
140
|
-
},
|
|
141
|
-
}, async ({ slug, language }) => {
|
|
142
|
-
const activeLanguage = language ?? "js_zh";
|
|
143
|
-
const docs = await (0, docs_service_1.getApiDocsByLanguage)(activeLanguage);
|
|
144
|
-
const target = docs.find((doc) => doc.slug === slug);
|
|
145
|
-
if (!target) {
|
|
146
|
-
return (0, tool_utils_1.createTextToolResult)(`未找到文档 ${slug}.md(语言: ${activeLanguage})。`, true);
|
|
147
|
-
}
|
|
148
|
-
return (0, tool_utils_1.createTextToolResult)([
|
|
149
|
-
`标题: ${target.title}`,
|
|
150
|
-
`语言: ${activeLanguage}`,
|
|
151
|
-
`URI: ${(0, docs_service_1.getDocUri)(activeLanguage, target.slug)}`,
|
|
152
|
-
`path: ${target.filePath}`,
|
|
153
|
-
"",
|
|
154
|
-
target.content,
|
|
155
|
-
].join("\n"));
|
|
156
|
-
});
|
|
157
39
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiDocsLanguage } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* 获取 docs 根目录
|
|
4
4
|
* @returns 返回 docs 目录绝对路径
|
|
@@ -14,29 +14,3 @@ export declare function getDocsRootDir(): string;
|
|
|
14
14
|
* const dir = getDocsDirByLanguage("js_zh")
|
|
15
15
|
*/
|
|
16
16
|
export declare function getDocsDirByLanguage(language: ApiDocsLanguage): string;
|
|
17
|
-
/**
|
|
18
|
-
* 读取指定语言的 API 文档列表
|
|
19
|
-
* @param language 文档语言
|
|
20
|
-
* @returns 返回文档条目数组(按 slug 升序)
|
|
21
|
-
* @example
|
|
22
|
-
* const docs = await getApiDocsByLanguage("python")
|
|
23
|
-
*/
|
|
24
|
-
export declare function getApiDocsByLanguage(language: ApiDocsLanguage): Promise<ApiDocItem[]>;
|
|
25
|
-
/**
|
|
26
|
-
* 对文档按查询词打分,用于检索排序
|
|
27
|
-
* @param doc 文档条目
|
|
28
|
-
* @param normalizedQuery 已转小写的查询词
|
|
29
|
-
* @returns 分数,0 表示不命中
|
|
30
|
-
* @example
|
|
31
|
-
* const score = scoreApiDoc(doc, "click")
|
|
32
|
-
*/
|
|
33
|
-
export declare function scoreApiDoc(doc: ApiDocItem, normalizedQuery: string): number;
|
|
34
|
-
/**
|
|
35
|
-
* 生成文档 URI(用于资源与文本返回)
|
|
36
|
-
* @param language 文档语言
|
|
37
|
-
* @param slug 文档分类
|
|
38
|
-
* @returns 返回 MCP 资源 URI 字符串
|
|
39
|
-
* @example
|
|
40
|
-
* const uri = getDocUri("js_zh", "device")
|
|
41
|
-
*/
|
|
42
|
-
export declare function getDocUri(language: ApiDocsLanguage, slug: string): string;
|
package/dist/mcp/docs-service.js
CHANGED
|
@@ -35,10 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.getDocsRootDir = getDocsRootDir;
|
|
37
37
|
exports.getDocsDirByLanguage = getDocsDirByLanguage;
|
|
38
|
-
exports.getApiDocsByLanguage = getApiDocsByLanguage;
|
|
39
|
-
exports.scoreApiDoc = scoreApiDoc;
|
|
40
|
-
exports.getDocUri = getDocUri;
|
|
41
|
-
const fsExtra = __importStar(require("fs-extra"));
|
|
42
38
|
const path = __importStar(require("path"));
|
|
43
39
|
/**
|
|
44
40
|
* 获取 docs 根目录
|
|
@@ -65,64 +61,3 @@ function getDocsDirByLanguage(language) {
|
|
|
65
61
|
}
|
|
66
62
|
return path.join(getDocsRootDir(), "apipython");
|
|
67
63
|
}
|
|
68
|
-
/**
|
|
69
|
-
* 读取指定语言的 API 文档列表
|
|
70
|
-
* @param language 文档语言
|
|
71
|
-
* @returns 返回文档条目数组(按 slug 升序)
|
|
72
|
-
* @example
|
|
73
|
-
* const docs = await getApiDocsByLanguage("python")
|
|
74
|
-
*/
|
|
75
|
-
async function getApiDocsByLanguage(language) {
|
|
76
|
-
const docsDir = getDocsDirByLanguage(language);
|
|
77
|
-
const fileNames = await fsExtra.readdir(docsDir);
|
|
78
|
-
const mdFiles = fileNames
|
|
79
|
-
.filter((name) => name.toLowerCase().endsWith(".md"))
|
|
80
|
-
.sort();
|
|
81
|
-
const docs = [];
|
|
82
|
-
for (const fileName of mdFiles) {
|
|
83
|
-
const filePath = path.join(docsDir, fileName);
|
|
84
|
-
const content = await fsExtra.readFile(filePath, "utf8");
|
|
85
|
-
const slug = path.basename(fileName, ".md");
|
|
86
|
-
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
87
|
-
const title = titleMatch?.[1]?.trim() || slug;
|
|
88
|
-
docs.push({
|
|
89
|
-
slug,
|
|
90
|
-
title,
|
|
91
|
-
content,
|
|
92
|
-
filePath,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
return docs;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* 对文档按查询词打分,用于检索排序
|
|
99
|
-
* @param doc 文档条目
|
|
100
|
-
* @param normalizedQuery 已转小写的查询词
|
|
101
|
-
* @returns 分数,0 表示不命中
|
|
102
|
-
* @example
|
|
103
|
-
* const score = scoreApiDoc(doc, "click")
|
|
104
|
-
*/
|
|
105
|
-
function scoreApiDoc(doc, normalizedQuery) {
|
|
106
|
-
let score = 0;
|
|
107
|
-
if (doc.title.toLowerCase().includes(normalizedQuery)) {
|
|
108
|
-
score += 50;
|
|
109
|
-
}
|
|
110
|
-
if (doc.slug.toLowerCase().includes(normalizedQuery)) {
|
|
111
|
-
score += 40;
|
|
112
|
-
}
|
|
113
|
-
if (doc.content.toLowerCase().includes(normalizedQuery)) {
|
|
114
|
-
score += 10;
|
|
115
|
-
}
|
|
116
|
-
return score;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* 生成文档 URI(用于资源与文本返回)
|
|
120
|
-
* @param language 文档语言
|
|
121
|
-
* @param slug 文档分类
|
|
122
|
-
* @returns 返回 MCP 资源 URI 字符串
|
|
123
|
-
* @example
|
|
124
|
-
* const uri = getDocUri("js_zh", "device")
|
|
125
|
-
*/
|
|
126
|
-
function getDocUri(language, slug) {
|
|
127
|
-
return `kuaijs://docs/${language}/${slug}`;
|
|
128
|
-
}
|