@llmindset/hf-mcp 0.1.18 → 0.1.19
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/docs-search/doc-fetch.d.ts +1 -1
- package/dist/docs-search/doc-fetch.d.ts.map +1 -1
- package/dist/docs-search/doc-fetch.js +1 -2
- package/dist/docs-search/doc-fetch.js.map +1 -1
- package/dist/docs-search/docs-semantic-search.d.ts +4 -4
- package/dist/docs-search/docs-semantic-search.d.ts.map +1 -1
- package/dist/docs-search/docs-semantic-search.js +55 -31
- package/dist/docs-search/docs-semantic-search.js.map +1 -1
- package/dist/docs-search/docs-semantic-search.test.js +60 -21
- package/dist/docs-search/docs-semantic-search.test.js.map +1 -1
- package/dist/tool-ids.d.ts +6 -6
- package/dist/tool-ids.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/docs-search/doc-fetch.ts +1 -2
- package/src/docs-search/docs-semantic-search.test.ts +79 -32
- package/src/docs-search/docs-semantic-search.ts +72 -35
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const DOC_FETCH_CONFIG: {
|
|
3
|
-
readonly name: "
|
|
3
|
+
readonly name: "hf_doc_fetch";
|
|
4
4
|
readonly description: "Fetch a document from the Hugging Face documentation library.";
|
|
5
5
|
readonly schema: z.ZodObject<{
|
|
6
6
|
doc_url: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doc-fetch.d.ts","sourceRoot":"","sources":["../../src/docs-search/doc-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAgBnB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAkBrE,qBAAa,YAAY;IAIxB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"doc-fetch.d.ts","sourceRoot":"","sources":["../../src/docs-search/doc-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAgBnB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAkBrE,qBAAa,YAAY;IAIxB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAgC3B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAgBzC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { DOC_MAPPINGS } from './doc-mappings.js';
|
|
3
3
|
export const DOC_FETCH_CONFIG = {
|
|
4
|
-
name: '
|
|
4
|
+
name: 'hf_doc_fetch',
|
|
5
5
|
description: 'Fetch a document from the Hugging Face documentation library.',
|
|
6
6
|
schema: z.object({
|
|
7
7
|
doc_url: z
|
|
@@ -33,7 +33,6 @@ export class DocFetchTool {
|
|
|
33
33
|
const githubUrl = `https://raw.githubusercontent.com/${mapping.repo_id}/refs/heads/main/${mapping.doc_folder}/${filePath}`;
|
|
34
34
|
fetchUrl = githubUrl;
|
|
35
35
|
}
|
|
36
|
-
console.error(fetchUrl);
|
|
37
36
|
return fetchUrl;
|
|
38
37
|
}
|
|
39
38
|
async fetch(url) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doc-fetch.js","sourceRoot":"","sources":["../../src/docs-search/doc-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC/B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,+DAA+D;IAC5E,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC;aACR,MAAM,EAAE;aACR,GAAG,CAAC,EAAE,EAAE,oDAAoD,CAAC;aAC7D,GAAG,CAAC,GAAG,EAAE,gBAAgB,CAAC;aAC1B,QAAQ,CAAC,gCAAgC,CAAC;KAC5C,CAAC;IACF,WAAW,EAAE;QACZ,KAAK,EAAE,gDAAgD;QACvD,eAAe,EAAE,KAAK;QACtB,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;KACnB;CACQ,CAAC;AAoBX,MAAM,OAAO,YAAY;IAIxB,UAAU,CAAC,KAAa;QAEvB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,8BAA8B,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,CAAC;QAGD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAGtF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAGnC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC;YAGpE,MAAM,SAAS,GAAG,qCAAqC,OAAO,CAAC,OAAO,oBAAoB,OAAO,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;YAC3H,QAAQ,GAAG,SAAS,CAAC;QACtB,CAAC;QAGD,OAAO,
|
|
1
|
+
{"version":3,"file":"doc-fetch.js","sourceRoot":"","sources":["../../src/docs-search/doc-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC/B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,+DAA+D;IAC5E,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC;aACR,MAAM,EAAE;aACR,GAAG,CAAC,EAAE,EAAE,oDAAoD,CAAC;aAC7D,GAAG,CAAC,GAAG,EAAE,gBAAgB,CAAC;aAC1B,QAAQ,CAAC,gCAAgC,CAAC;KAC5C,CAAC;IACF,WAAW,EAAE;QACZ,KAAK,EAAE,gDAAgD;QACvD,eAAe,EAAE,KAAK;QACtB,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;KACnB;CACQ,CAAC;AAoBX,MAAM,OAAO,YAAY;IAIxB,UAAU,CAAC,KAAa;QAEvB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,8BAA8B,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,CAAC;QAGD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAGtF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAGnC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC;YAGpE,MAAM,SAAS,GAAG,qCAAqC,OAAO,CAAC,OAAO,oBAAoB,OAAO,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;YAC3H,QAAQ,GAAG,SAAS,CAAC;QACtB,CAAC;QAGD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAKD,KAAK,CAAC,KAAK,CAAC,GAAW;QACtB,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAEvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;YAExC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACxF,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtC,OAAO,OAAO,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAC1G,CAAC;IACF,CAAC;CACD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { HfApiCall } from '../hf-api-call.js';
|
|
3
3
|
export declare const DOCS_SEMANTIC_SEARCH_CONFIG: {
|
|
4
|
-
readonly name: "
|
|
5
|
-
readonly description:
|
|
4
|
+
readonly name: "hf_doc_search";
|
|
5
|
+
readonly description: "Search the Hugging Face documentation library. Returns excerpts grouped by Product and Document.";
|
|
6
6
|
readonly schema: z.ZodObject<{
|
|
7
7
|
query: z.ZodString;
|
|
8
8
|
product: z.ZodOptional<z.ZodString>;
|
|
@@ -14,7 +14,7 @@ export declare const DOCS_SEMANTIC_SEARCH_CONFIG: {
|
|
|
14
14
|
product?: string | undefined;
|
|
15
15
|
}>;
|
|
16
16
|
readonly annotations: {
|
|
17
|
-
readonly title: "Hugging Face Documentation Search";
|
|
17
|
+
readonly title: "Hugging Face Documentation Library Search";
|
|
18
18
|
readonly destructiveHint: false;
|
|
19
19
|
readonly readOnlyHint: true;
|
|
20
20
|
readonly openWorldHint: true;
|
|
@@ -35,7 +35,7 @@ interface DocSearchApiParams {
|
|
|
35
35
|
}
|
|
36
36
|
export declare class DocSearchTool extends HfApiCall<DocSearchApiParams, DocSearchResult[]> {
|
|
37
37
|
constructor(hfToken?: string, apiUrl?: string);
|
|
38
|
-
search(
|
|
38
|
+
search(params: DocSearchParams): Promise<string>;
|
|
39
39
|
}
|
|
40
40
|
export {};
|
|
41
41
|
//# sourceMappingURL=docs-semantic-search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-semantic-search.d.ts","sourceRoot":"","sources":["../../src/docs-search/docs-semantic-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI9C,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;CAsB9B,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAEjF,UAAU,eAAe;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,kBAAkB;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,qBAAa,aAAc,SAAQ,SAAS,CAAC,kBAAkB,EAAE,eAAe,EAAE,CAAC;gBAKtE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,SAAkC;IAQhE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"docs-semantic-search.d.ts","sourceRoot":"","sources":["../../src/docs-search/docs-semantic-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI9C,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;CAsB9B,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAEjF,UAAU,eAAe;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,kBAAkB;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,qBAAa,aAAc,SAAQ,SAAS,CAAC,kBAAkB,EAAE,eAAe,EAAE,CAAC;gBAKtE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,SAAkC;IAQhE,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;CAyBtD"}
|
|
@@ -3,9 +3,8 @@ import { HfApiCall } from '../hf-api-call.js';
|
|
|
3
3
|
import { escapeMarkdown } from '../utilities.js';
|
|
4
4
|
import { DOC_FETCH_CONFIG } from './doc-fetch.js';
|
|
5
5
|
export const DOCS_SEMANTIC_SEARCH_CONFIG = {
|
|
6
|
-
name: '
|
|
7
|
-
description: 'Search the Hugging Face documentation library
|
|
8
|
-
'grouped by Product and document page.',
|
|
6
|
+
name: 'hf_doc_search',
|
|
7
|
+
description: 'Search the Hugging Face documentation library. Returns excerpts grouped by Product and Document.',
|
|
9
8
|
schema: z.object({
|
|
10
9
|
query: z
|
|
11
10
|
.string()
|
|
@@ -15,10 +14,10 @@ export const DOCS_SEMANTIC_SEARCH_CONFIG = {
|
|
|
15
14
|
product: z
|
|
16
15
|
.string()
|
|
17
16
|
.optional()
|
|
18
|
-
.describe('Filter by
|
|
17
|
+
.describe('Filter by Product (e.g., "hub", "dataset-viewer", "transformers"). Supply when known for focused results'),
|
|
19
18
|
}),
|
|
20
19
|
annotations: {
|
|
21
|
-
title: 'Hugging Face Documentation Search',
|
|
20
|
+
title: 'Hugging Face Documentation Library Search',
|
|
22
21
|
destructiveHint: false,
|
|
23
22
|
readOnlyHint: true,
|
|
24
23
|
openWorldHint: true,
|
|
@@ -28,21 +27,21 @@ export class DocSearchTool extends HfApiCall {
|
|
|
28
27
|
constructor(hfToken, apiUrl = 'https://hf.co/api/docs/search') {
|
|
29
28
|
super(apiUrl, hfToken);
|
|
30
29
|
}
|
|
31
|
-
async search(
|
|
30
|
+
async search(params) {
|
|
32
31
|
try {
|
|
33
|
-
if (!query)
|
|
32
|
+
if (!params.query)
|
|
34
33
|
return 'No query provided';
|
|
35
|
-
const
|
|
36
|
-
if (product) {
|
|
37
|
-
|
|
34
|
+
const apiParams = { q: params.query.toLowerCase() };
|
|
35
|
+
if (params.product) {
|
|
36
|
+
apiParams.product = params.product;
|
|
38
37
|
}
|
|
39
|
-
const results = await this.callApi(
|
|
38
|
+
const results = await this.callApi(apiParams);
|
|
40
39
|
if (results.length === 0) {
|
|
41
|
-
return product
|
|
42
|
-
? `No documentation found for query '${query}' in product '${product}'`
|
|
43
|
-
: `No documentation found for query '${query}'`;
|
|
40
|
+
return params.product
|
|
41
|
+
? `No documentation found for query '${params.query}' in product '${params.product}'`
|
|
42
|
+
: `No documentation found for query '${params.query}'`;
|
|
44
43
|
}
|
|
45
|
-
return formatSearchResults(query, results, product);
|
|
44
|
+
return formatSearchResults(params.query, results, params.product);
|
|
46
45
|
}
|
|
47
46
|
catch (error) {
|
|
48
47
|
if (error instanceof Error) {
|
|
@@ -61,33 +60,56 @@ function groupResults(results) {
|
|
|
61
60
|
const productGroup = grouped.get(result.product);
|
|
62
61
|
if (!productGroup)
|
|
63
62
|
continue;
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
const baseUrl = result.source_page_url.split('#')[0] || result.source_page_url;
|
|
64
|
+
if (!productGroup.has(baseUrl)) {
|
|
65
|
+
productGroup.set(baseUrl, []);
|
|
66
66
|
}
|
|
67
|
-
const pageResults = productGroup.get(
|
|
67
|
+
const pageResults = productGroup.get(baseUrl);
|
|
68
68
|
if (pageResults) {
|
|
69
69
|
pageResults.push(result);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
return grouped;
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function groupBySection(pageResults) {
|
|
75
|
+
const sectionGroups = new Map();
|
|
76
|
+
for (const result of pageResults) {
|
|
77
|
+
const section = result.heading2;
|
|
78
|
+
if (!sectionGroups.has(section)) {
|
|
79
|
+
sectionGroups.set(section, []);
|
|
80
|
+
}
|
|
81
|
+
const sectionResults = sectionGroups.get(section);
|
|
82
|
+
if (sectionResults) {
|
|
83
|
+
sectionResults.push(result);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return sectionGroups;
|
|
87
|
+
}
|
|
88
|
+
function formatSectionExcerpts(section, results) {
|
|
75
89
|
const lines = [];
|
|
76
|
-
if (
|
|
77
|
-
|
|
90
|
+
if (section) {
|
|
91
|
+
if (results.length > 1) {
|
|
92
|
+
lines.push(`#### Excerpts from the "${escapeMarkdown(section)}" section`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
lines.push(`#### Excerpt from the "${escapeMarkdown(section)}" section`);
|
|
96
|
+
}
|
|
97
|
+
lines.push('');
|
|
98
|
+
}
|
|
99
|
+
for (const result of results) {
|
|
100
|
+
const cleanText = result.text
|
|
101
|
+
.replace(/<[^>]*>/g, '')
|
|
102
|
+
.replace(/\n\s*\n/g, '\n')
|
|
103
|
+
.trim();
|
|
104
|
+
lines.push(cleanText);
|
|
105
|
+
lines.push('');
|
|
78
106
|
}
|
|
79
|
-
const cleanText = result.text
|
|
80
|
-
.replace(/<[^>]*>/g, '')
|
|
81
|
-
.replace(/\n\s*\n/g, '\n')
|
|
82
|
-
.trim();
|
|
83
|
-
lines.push(cleanText);
|
|
84
|
-
lines.push('');
|
|
85
107
|
return lines.join('\n');
|
|
86
108
|
}
|
|
87
109
|
function formatSearchResults(query, results, productFilter) {
|
|
88
110
|
const lines = [];
|
|
89
111
|
const filterText = productFilter ? ` (filtered by product: ${productFilter})` : '';
|
|
90
|
-
lines.push(`# Documentation Search Results for "${escapeMarkdown(query)}"${filterText}`);
|
|
112
|
+
lines.push(`# Documentation Library Search Results for "${escapeMarkdown(query)}"${filterText}`);
|
|
91
113
|
lines.push('');
|
|
92
114
|
lines.push(`Found ${results.length} results`);
|
|
93
115
|
lines.push('');
|
|
@@ -126,13 +148,15 @@ function formatSearchResults(query, results, productFilter) {
|
|
|
126
148
|
const hitCount = pageResults.length > 1 ? ` (${pageResults.length} results)` : '';
|
|
127
149
|
lines.push(`### Results from [${escapeMarkdown(pageTitle)}](${url})${hitCount}`);
|
|
128
150
|
lines.push('');
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
const sectionGroups = groupBySection(pageResults);
|
|
152
|
+
for (const [section, sectionResults] of sectionGroups) {
|
|
153
|
+
lines.push(formatSectionExcerpts(section, sectionResults));
|
|
131
154
|
}
|
|
132
155
|
}
|
|
133
156
|
}
|
|
134
157
|
lines.push('---');
|
|
135
|
-
lines.push(
|
|
158
|
+
lines.push('');
|
|
159
|
+
lines.push(`Use the "${DOC_FETCH_CONFIG.name}" tool to fetch a document from the library.`);
|
|
136
160
|
return lines.join('\n');
|
|
137
161
|
}
|
|
138
162
|
//# sourceMappingURL=docs-semantic-search.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-semantic-search.js","sourceRoot":"","sources":["../../src/docs-search/docs-semantic-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,CAAC,MAAM,2BAA2B,GAAG;IAC1C,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"docs-semantic-search.js","sourceRoot":"","sources":["../../src/docs-search/docs-semantic-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
2
|
import { DocSearchTool } from './docs-semantic-search.js';
|
|
3
|
+
import { DOC_FETCH_CONFIG } from './doc-fetch.js';
|
|
3
4
|
const mockFetch = vi.fn();
|
|
4
5
|
global.fetch = mockFetch;
|
|
5
6
|
describe('DocSearchTool', () => {
|
|
@@ -9,16 +10,15 @@ describe('DocSearchTool', () => {
|
|
|
9
10
|
vi.clearAllMocks();
|
|
10
11
|
});
|
|
11
12
|
describe('search', () => {
|
|
12
|
-
it('should return
|
|
13
|
-
|
|
14
|
-
expect(result).toBe('No query provided');
|
|
13
|
+
it('should return error when query is too short', async () => {
|
|
14
|
+
await expect(docSearchTool.search({ query: 'ab' })).rejects.toThrow();
|
|
15
15
|
});
|
|
16
16
|
it('should return no results message when API returns empty array', async () => {
|
|
17
17
|
mockFetch.mockResolvedValueOnce({
|
|
18
18
|
ok: true,
|
|
19
19
|
json: () => Promise.resolve([]),
|
|
20
20
|
});
|
|
21
|
-
const result = await docSearchTool.search('nonexistent');
|
|
21
|
+
const result = await docSearchTool.search({ query: 'nonexistent' });
|
|
22
22
|
expect(result).toBe(`No documentation found for query 'nonexistent'`);
|
|
23
23
|
});
|
|
24
24
|
it('should return no results message with product filter', async () => {
|
|
@@ -26,7 +26,7 @@ describe('DocSearchTool', () => {
|
|
|
26
26
|
ok: true,
|
|
27
27
|
json: () => Promise.resolve([]),
|
|
28
28
|
});
|
|
29
|
-
const result = await docSearchTool.search('nonexistent', 'hub');
|
|
29
|
+
const result = await docSearchTool.search({ query: 'nonexistent', product: 'hub' });
|
|
30
30
|
expect(result).toBe(`No documentation found for query 'nonexistent' in product 'hub'`);
|
|
31
31
|
});
|
|
32
32
|
it('should format results grouped by product and page', async () => {
|
|
@@ -59,8 +59,8 @@ describe('DocSearchTool', () => {
|
|
|
59
59
|
ok: true,
|
|
60
60
|
json: () => Promise.resolve(sampleResults),
|
|
61
61
|
});
|
|
62
|
-
const result = await docSearchTool.search('analytics');
|
|
63
|
-
expect(result).toContain('# Documentation Search Results for "analytics"');
|
|
62
|
+
const result = await docSearchTool.search({ query: 'analytics' });
|
|
63
|
+
expect(result).toContain('# Documentation Library Search Results for "analytics"');
|
|
64
64
|
expect(result).toContain('Found 3 results');
|
|
65
65
|
const hubIndex = result.indexOf('## Results for Product: hub');
|
|
66
66
|
const datasetViewerIndex = result.indexOf('## Results for Product: dataset-viewer');
|
|
@@ -69,14 +69,14 @@ describe('DocSearchTool', () => {
|
|
|
69
69
|
expect(datasetViewerIndex).toBeGreaterThan(-1);
|
|
70
70
|
expect(result).toContain('## Results for Product: hub (2 results)');
|
|
71
71
|
expect(result).toContain('## Results for Product: dataset-viewer (1 results)');
|
|
72
|
-
expect(result).toContain('### Results from [Analytics](https://huggingface.co/docs/hub/enterprise-hub-analytics
|
|
73
|
-
expect(result).toContain('### Results from [Quickstart](https://huggingface.co/docs/dataset-viewer/quick_start
|
|
74
|
-
expect(result).toContain('
|
|
75
|
-
expect(result).toContain('
|
|
72
|
+
expect(result).toContain('### Results from [Analytics](https://huggingface.co/docs/hub/enterprise-hub-analytics)');
|
|
73
|
+
expect(result).toContain('### Results from [Quickstart](https://huggingface.co/docs/dataset-viewer/quick_start)');
|
|
74
|
+
expect(result).toContain('#### Excerpt from the "Export Analytics as CSV" section');
|
|
75
|
+
expect(result).toContain('#### Excerpt from the "View Analytics" section');
|
|
76
76
|
expect(result).toContain('Download a comprehensive CSV file containing analytics');
|
|
77
77
|
expect(result).toContain('View analytics for your repositories');
|
|
78
78
|
expect(result).toContain('In this quickstart, you will learn how to use the dataset viewer REST API');
|
|
79
|
-
expect(result).toContain('Use the "
|
|
79
|
+
expect(result).toContain('Use the "' + DOC_FETCH_CONFIG.name + '" tool to fetch a document from the library.');
|
|
80
80
|
});
|
|
81
81
|
it('should handle results without heading2', async () => {
|
|
82
82
|
const sampleResults = [
|
|
@@ -92,8 +92,8 @@ describe('DocSearchTool', () => {
|
|
|
92
92
|
ok: true,
|
|
93
93
|
json: () => Promise.resolve(sampleResults),
|
|
94
94
|
});
|
|
95
|
-
const result = await docSearchTool.search('transformers');
|
|
96
|
-
expect(result).not.toContain('
|
|
95
|
+
const result = await docSearchTool.search({ query: 'transformers' });
|
|
96
|
+
expect(result).not.toContain('#### Excerpt from');
|
|
97
97
|
expect(result).toContain('This is a simple text without heading2');
|
|
98
98
|
});
|
|
99
99
|
it('should properly escape markdown special characters', async () => {
|
|
@@ -111,9 +111,9 @@ describe('DocSearchTool', () => {
|
|
|
111
111
|
ok: true,
|
|
112
112
|
json: () => Promise.resolve(sampleResults),
|
|
113
113
|
});
|
|
114
|
-
const result = await docSearchTool.search('special');
|
|
114
|
+
const result = await docSearchTool.search({ query: 'special' });
|
|
115
115
|
expect(result).toContain('Special \\* Characters');
|
|
116
|
-
expect(result).toContain('"Section with [brackets]"');
|
|
116
|
+
expect(result).toContain('#### Excerpt from the "Section with [brackets]" section');
|
|
117
117
|
});
|
|
118
118
|
it('should clean HTML tags from text', async () => {
|
|
119
119
|
const sampleResults = [
|
|
@@ -129,7 +129,7 @@ describe('DocSearchTool', () => {
|
|
|
129
129
|
ok: true,
|
|
130
130
|
json: () => Promise.resolve(sampleResults),
|
|
131
131
|
});
|
|
132
|
-
const result = await docSearchTool.search('html');
|
|
132
|
+
const result = await docSearchTool.search({ query: 'html' });
|
|
133
133
|
expect(result).toContain('Text with HTML tags and');
|
|
134
134
|
expect(result).not.toContain('<div');
|
|
135
135
|
expect(result).not.toContain('<img');
|
|
@@ -176,7 +176,7 @@ describe('DocSearchTool', () => {
|
|
|
176
176
|
ok: true,
|
|
177
177
|
json: () => Promise.resolve(sampleResults),
|
|
178
178
|
});
|
|
179
|
-
const result = await docSearchTool.search('test');
|
|
179
|
+
const result = await docSearchTool.search({ query: 'test' });
|
|
180
180
|
const hubIndex = result.indexOf('## Results for Product: hub');
|
|
181
181
|
const transformersIndex = result.indexOf('## Results for Product: transformers');
|
|
182
182
|
const datasetsIndex = result.indexOf('## Results for Product: datasets');
|
|
@@ -193,12 +193,51 @@ describe('DocSearchTool', () => {
|
|
|
193
193
|
ok: true,
|
|
194
194
|
json: () => Promise.resolve([]),
|
|
195
195
|
});
|
|
196
|
-
await docSearchTool.search('test', 'hub');
|
|
196
|
+
await docSearchTool.search({ query: 'test', product: 'hub' });
|
|
197
197
|
expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('q=test&product=hub'), expect.any(Object));
|
|
198
198
|
});
|
|
199
|
+
it('should group results from the same page with different anchors together', async () => {
|
|
200
|
+
const sampleResults = [
|
|
201
|
+
{
|
|
202
|
+
text: 'First result from section 1',
|
|
203
|
+
product: 'hub',
|
|
204
|
+
heading1: 'Analytics',
|
|
205
|
+
source_page_url: 'https://huggingface.co/docs/hub/analytics#section1',
|
|
206
|
+
source_page_title: 'Analytics Page',
|
|
207
|
+
heading2: 'Section 1',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
text: 'Second result from section 2',
|
|
211
|
+
product: 'hub',
|
|
212
|
+
heading1: 'Analytics',
|
|
213
|
+
source_page_url: 'https://huggingface.co/docs/hub/analytics#section2',
|
|
214
|
+
source_page_title: 'Analytics Page',
|
|
215
|
+
heading2: 'Section 2',
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
text: 'Third result from section 3',
|
|
219
|
+
product: 'hub',
|
|
220
|
+
heading1: 'Analytics',
|
|
221
|
+
source_page_url: 'https://huggingface.co/docs/hub/analytics#section3',
|
|
222
|
+
source_page_title: 'Analytics Page',
|
|
223
|
+
heading2: 'Section 3',
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
mockFetch.mockResolvedValueOnce({
|
|
227
|
+
ok: true,
|
|
228
|
+
json: () => Promise.resolve(sampleResults),
|
|
229
|
+
});
|
|
230
|
+
const result = await docSearchTool.search({ query: 'analytics' });
|
|
231
|
+
expect(result).toContain('### Results from [Analytics](https://huggingface.co/docs/hub/analytics) (3 results)');
|
|
232
|
+
expect(result).toContain('First result from section 1');
|
|
233
|
+
expect(result).toContain('Second result from section 2');
|
|
234
|
+
expect(result).toContain('Third result from section 3');
|
|
235
|
+
const resultsFromCount = (result.match(/### Results from/g) || []).length;
|
|
236
|
+
expect(resultsFromCount).toBe(1);
|
|
237
|
+
});
|
|
199
238
|
it('should handle API errors gracefully', async () => {
|
|
200
239
|
mockFetch.mockRejectedValueOnce(new Error('Network error'));
|
|
201
|
-
await expect(docSearchTool.search('test')).rejects.toThrow('Failed to search documentation:');
|
|
240
|
+
await expect(docSearchTool.search({ query: 'test' })).rejects.toThrow('Failed to search documentation:');
|
|
202
241
|
});
|
|
203
242
|
});
|
|
204
243
|
describe('groupResults', () => {
|
|
@@ -230,7 +269,7 @@ describe('DocSearchTool', () => {
|
|
|
230
269
|
ok: true,
|
|
231
270
|
json: () => Promise.resolve(sampleResults),
|
|
232
271
|
});
|
|
233
|
-
const result = await docSearchTool.search('test');
|
|
272
|
+
const result = await docSearchTool.search({ query: 'test' });
|
|
234
273
|
expect(result).toContain('## Results for Product: hub');
|
|
235
274
|
expect(result).toContain('## Results for Product: transformers');
|
|
236
275
|
const result1Index = result.indexOf('Result 1');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-semantic-search.test.js","sourceRoot":"","sources":["../../src/docs-search/docs-semantic-search.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"docs-semantic-search.test.js","sourceRoot":"","sources":["../../src/docs-search/docs-semantic-search.test.ts"],"names":[],"mappings":"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"}
|
package/dist/tool-ids.d.ts
CHANGED
|
@@ -7,18 +7,18 @@ export declare const DATASET_DETAIL_TOOL_ID: "dataset_details";
|
|
|
7
7
|
export declare const DUPLICATE_SPACE_TOOL_ID: "duplicate_space";
|
|
8
8
|
export declare const SPACE_INFO_TOOL_ID: "space_info";
|
|
9
9
|
export declare const SPACE_FILES_TOOL_ID: "space_files";
|
|
10
|
-
export declare const DOCS_SEMANTIC_SEARCH_TOOL_ID: "
|
|
11
|
-
export declare const DOC_FETCH_TOOL_ID: "
|
|
10
|
+
export declare const DOCS_SEMANTIC_SEARCH_TOOL_ID: "hf_doc_search";
|
|
11
|
+
export declare const DOC_FETCH_TOOL_ID: "hf_doc_fetch";
|
|
12
12
|
export declare const USER_SUMMARY_PROMPT_ID: "User Summary";
|
|
13
13
|
export declare const PAPER_SUMMARY_PROMPT_ID: "Paper Summary";
|
|
14
|
-
export declare const ALL_BUILTIN_TOOL_IDS: readonly ["space_search", "model_search", "model_details", "paper_search", "dataset_search", "dataset_details", "duplicate_space", "space_info", "space_files", "
|
|
14
|
+
export declare const ALL_BUILTIN_TOOL_IDS: readonly ["space_search", "model_search", "model_details", "paper_search", "dataset_search", "dataset_details", "duplicate_space", "space_info", "space_files", "hf_doc_search", "hf_doc_fetch"];
|
|
15
15
|
export declare const TOOL_ID_GROUPS: {
|
|
16
|
-
readonly search: readonly ["space_search", "model_search", "dataset_search", "paper_search", "
|
|
16
|
+
readonly search: readonly ["space_search", "model_search", "dataset_search", "paper_search", "hf_doc_search"];
|
|
17
17
|
readonly spaces: readonly ["space_search", "duplicate_space", "space_info", "space_files"];
|
|
18
18
|
readonly detail: readonly ["model_details", "dataset_details"];
|
|
19
|
-
readonly docs: readonly ["
|
|
19
|
+
readonly docs: readonly ["hf_doc_search", "hf_doc_fetch"];
|
|
20
20
|
readonly hf_api: readonly ["space_search", "model_search", "dataset_search", "paper_search", "model_details", "dataset_details"];
|
|
21
|
-
readonly all: readonly ["space_search", "model_search", "model_details", "paper_search", "dataset_search", "dataset_details", "duplicate_space", "space_info", "space_files", "
|
|
21
|
+
readonly all: readonly ["space_search", "model_search", "model_details", "paper_search", "dataset_search", "dataset_details", "duplicate_space", "space_info", "space_files", "hf_doc_search", "hf_doc_fetch"];
|
|
22
22
|
};
|
|
23
23
|
export type BuiltinToolId = (typeof ALL_BUILTIN_TOOL_IDS)[number];
|
|
24
24
|
export declare function isValidBuiltinToolId(toolId: string): toolId is BuiltinToolId;
|
package/dist/tool-ids.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-ids.d.ts","sourceRoot":"","sources":["../src/tool-ids.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,oBAAoB,gBAAmC,CAAC;AACrE,eAAO,MAAM,oBAAoB,gBAAgC,CAAC;AAClE,eAAO,MAAM,oBAAoB,iBAAgC,CAAC;AAClE,eAAO,MAAM,oBAAoB,gBAAgC,CAAC;AAClE,eAAO,MAAM,sBAAsB,kBAAkC,CAAC;AACtE,eAAO,MAAM,sBAAsB,mBAAkC,CAAC;AACtE,eAAO,MAAM,uBAAuB,mBAAmC,CAAC;AACxE,eAAO,MAAM,kBAAkB,cAA8B,CAAC;AAC9D,eAAO,MAAM,mBAAmB,eAA+B,CAAC;AAChE,eAAO,MAAM,4BAA4B,
|
|
1
|
+
{"version":3,"file":"tool-ids.d.ts","sourceRoot":"","sources":["../src/tool-ids.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,oBAAoB,gBAAmC,CAAC;AACrE,eAAO,MAAM,oBAAoB,gBAAgC,CAAC;AAClE,eAAO,MAAM,oBAAoB,iBAAgC,CAAC;AAClE,eAAO,MAAM,oBAAoB,gBAAgC,CAAC;AAClE,eAAO,MAAM,sBAAsB,kBAAkC,CAAC;AACtE,eAAO,MAAM,sBAAsB,mBAAkC,CAAC;AACtE,eAAO,MAAM,uBAAuB,mBAAmC,CAAC;AACxE,eAAO,MAAM,kBAAkB,cAA8B,CAAC;AAC9D,eAAO,MAAM,mBAAmB,eAA+B,CAAC;AAChE,eAAO,MAAM,4BAA4B,iBAAmC,CAAC;AAC7E,eAAO,MAAM,iBAAiB,gBAAwB,CAAC;AACvD,eAAO,MAAM,sBAAsB,gBAAkC,CAAC;AACtE,eAAO,MAAM,uBAAuB,iBAAmC,CAAC;AAIxE,eAAO,MAAM,oBAAoB,kMAYvB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;CAcjB,CAAC;AAGX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAGlE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,aAAa,CAE5E"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { DOC_MAPPINGS } from './doc-mappings.js';
|
|
3
3
|
|
|
4
4
|
export const DOC_FETCH_CONFIG = {
|
|
5
|
-
name: '
|
|
5
|
+
name: 'hf_doc_fetch',
|
|
6
6
|
description: 'Fetch a document from the Hugging Face documentation library.',
|
|
7
7
|
schema: z.object({
|
|
8
8
|
doc_url: z
|
|
@@ -67,7 +67,6 @@ export class DocFetchTool {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// Build the file path
|
|
70
|
-
console.error(fetchUrl);
|
|
71
70
|
return fetchUrl;
|
|
72
71
|
}
|
|
73
72
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
2
|
import { DocSearchTool } from './docs-semantic-search.js';
|
|
3
|
+
import { DOC_FETCH_CONFIG } from './doc-fetch.js';
|
|
3
4
|
|
|
4
5
|
// Mock the fetch function
|
|
5
6
|
const mockFetch = vi.fn();
|
|
@@ -14,9 +15,8 @@ describe('DocSearchTool', () => {
|
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
describe('search', () => {
|
|
17
|
-
it('should return
|
|
18
|
-
|
|
19
|
-
expect(result).toBe('No query provided');
|
|
18
|
+
it('should return error when query is too short', async () => {
|
|
19
|
+
await expect(docSearchTool.search({ query: 'ab' })).rejects.toThrow();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
it('should return no results message when API returns empty array', async () => {
|
|
@@ -25,7 +25,7 @@ describe('DocSearchTool', () => {
|
|
|
25
25
|
json: () => Promise.resolve([]),
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const result = await docSearchTool.search('nonexistent');
|
|
28
|
+
const result = await docSearchTool.search({ query: 'nonexistent' });
|
|
29
29
|
expect(result).toBe(`No documentation found for query 'nonexistent'`);
|
|
30
30
|
});
|
|
31
31
|
|
|
@@ -35,7 +35,7 @@ describe('DocSearchTool', () => {
|
|
|
35
35
|
json: () => Promise.resolve([]),
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
const result = await docSearchTool.search('nonexistent', 'hub');
|
|
38
|
+
const result = await docSearchTool.search({ query: 'nonexistent', product: 'hub' });
|
|
39
39
|
expect(result).toBe(`No documentation found for query 'nonexistent' in product 'hub'`);
|
|
40
40
|
});
|
|
41
41
|
|
|
@@ -71,10 +71,10 @@ describe('DocSearchTool', () => {
|
|
|
71
71
|
json: () => Promise.resolve(sampleResults),
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
const result = await docSearchTool.search('analytics');
|
|
74
|
+
const result = await docSearchTool.search({ query: 'analytics' });
|
|
75
75
|
|
|
76
76
|
// Check header
|
|
77
|
-
expect(result).toContain('# Documentation Search Results for "analytics"');
|
|
77
|
+
expect(result).toContain('# Documentation Library Search Results for "analytics"');
|
|
78
78
|
expect(result).toContain('Found 3 results');
|
|
79
79
|
|
|
80
80
|
// Check product grouping - hub should come before dataset-viewer (hub has 2 results, dataset-viewer has 1)
|
|
@@ -88,13 +88,15 @@ describe('DocSearchTool', () => {
|
|
|
88
88
|
expect(result).toContain('## Results for Product: hub (2 results)');
|
|
89
89
|
expect(result).toContain('## Results for Product: dataset-viewer (1 results)');
|
|
90
90
|
|
|
91
|
-
// Check page links
|
|
92
|
-
expect(result).toContain(
|
|
93
|
-
|
|
91
|
+
// Check page links (without anchors)
|
|
92
|
+
expect(result).toContain(
|
|
93
|
+
'### Results from [Analytics](https://huggingface.co/docs/hub/enterprise-hub-analytics)'
|
|
94
|
+
);
|
|
95
|
+
expect(result).toContain('### Results from [Quickstart](https://huggingface.co/docs/dataset-viewer/quick_start)');
|
|
94
96
|
|
|
95
97
|
// Check excerpts with heading2
|
|
96
|
-
expect(result).toContain('
|
|
97
|
-
expect(result).toContain('
|
|
98
|
+
expect(result).toContain('#### Excerpt from the "Export Analytics as CSV" section');
|
|
99
|
+
expect(result).toContain('#### Excerpt from the "View Analytics" section');
|
|
98
100
|
|
|
99
101
|
// Check excerpt content appears as plain text
|
|
100
102
|
expect(result).toContain('Download a comprehensive CSV file containing analytics');
|
|
@@ -102,7 +104,7 @@ describe('DocSearchTool', () => {
|
|
|
102
104
|
expect(result).toContain('In this quickstart, you will learn how to use the dataset viewer REST API');
|
|
103
105
|
|
|
104
106
|
// Check footer
|
|
105
|
-
expect(result).toContain('Use the "
|
|
107
|
+
expect(result).toContain('Use the "' + DOC_FETCH_CONFIG.name + '" tool to fetch a document from the library.');
|
|
106
108
|
});
|
|
107
109
|
|
|
108
110
|
it('should handle results without heading2', async () => {
|
|
@@ -121,10 +123,10 @@ describe('DocSearchTool', () => {
|
|
|
121
123
|
json: () => Promise.resolve(sampleResults),
|
|
122
124
|
});
|
|
123
125
|
|
|
124
|
-
const result = await docSearchTool.search('transformers');
|
|
126
|
+
const result = await docSearchTool.search({ query: 'transformers' });
|
|
125
127
|
|
|
126
128
|
// Should not contain "Excerpt from" when heading2 is missing
|
|
127
|
-
expect(result).not.toContain('
|
|
129
|
+
expect(result).not.toContain('#### Excerpt from');
|
|
128
130
|
expect(result).toContain('This is a simple text without heading2');
|
|
129
131
|
});
|
|
130
132
|
|
|
@@ -145,12 +147,12 @@ describe('DocSearchTool', () => {
|
|
|
145
147
|
json: () => Promise.resolve(sampleResults),
|
|
146
148
|
});
|
|
147
149
|
|
|
148
|
-
const result = await docSearchTool.search('special');
|
|
150
|
+
const result = await docSearchTool.search({ query: 'special' });
|
|
149
151
|
|
|
150
152
|
// Check that special characters are escaped in headings and page titles
|
|
151
153
|
expect(result).toContain('Special \\* Characters');
|
|
152
|
-
// Note: heading2 appears in
|
|
153
|
-
expect(result).toContain('"Section with [brackets]"');
|
|
154
|
+
// Note: heading2 appears in header text, but brackets don't get escaped
|
|
155
|
+
expect(result).toContain('#### Excerpt from the "Section with [brackets]" section');
|
|
154
156
|
});
|
|
155
157
|
|
|
156
158
|
it('should clean HTML tags from text', async () => {
|
|
@@ -169,7 +171,7 @@ describe('DocSearchTool', () => {
|
|
|
169
171
|
json: () => Promise.resolve(sampleResults),
|
|
170
172
|
});
|
|
171
173
|
|
|
172
|
-
const result = await docSearchTool.search('html');
|
|
174
|
+
const result = await docSearchTool.search({ query: 'html' });
|
|
173
175
|
|
|
174
176
|
// HTML tags should be removed
|
|
175
177
|
expect(result).toContain('Text with HTML tags and');
|
|
@@ -224,9 +226,9 @@ describe('DocSearchTool', () => {
|
|
|
224
226
|
json: () => Promise.resolve(sampleResults),
|
|
225
227
|
});
|
|
226
228
|
|
|
227
|
-
const result = await docSearchTool.search('test');
|
|
229
|
+
const result = await docSearchTool.search({ query: 'test' });
|
|
228
230
|
|
|
229
|
-
// Check product order by count: hub (3) > transformers (1) = datasets (1)
|
|
231
|
+
// Check product order by count: hub (3) > transformers (1) = datasets (1)
|
|
230
232
|
const hubIndex = result.indexOf('## Results for Product: hub');
|
|
231
233
|
const transformersIndex = result.indexOf('## Results for Product: transformers');
|
|
232
234
|
const datasetsIndex = result.indexOf('## Results for Product: datasets');
|
|
@@ -236,7 +238,7 @@ describe('DocSearchTool', () => {
|
|
|
236
238
|
|
|
237
239
|
// Check that hub shows total count
|
|
238
240
|
expect(result).toContain('## Results for Product: hub (3 results)');
|
|
239
|
-
|
|
241
|
+
|
|
240
242
|
// Check page order within hub product: page1 (2 results) should come before page2 (1 result)
|
|
241
243
|
const page1Index = result.indexOf('https://huggingface.co/docs/hub/page1');
|
|
242
244
|
const page2Index = result.indexOf('https://huggingface.co/docs/hub/page2');
|
|
@@ -252,18 +254,63 @@ describe('DocSearchTool', () => {
|
|
|
252
254
|
json: () => Promise.resolve([]),
|
|
253
255
|
});
|
|
254
256
|
|
|
255
|
-
await docSearchTool.search('test', 'hub');
|
|
257
|
+
await docSearchTool.search({ query: 'test', product: 'hub' });
|
|
256
258
|
|
|
257
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
259
|
+
expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('q=test&product=hub'), expect.any(Object));
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should group results from the same page with different anchors together', async () => {
|
|
263
|
+
const sampleResults = [
|
|
264
|
+
{
|
|
265
|
+
text: 'First result from section 1',
|
|
266
|
+
product: 'hub',
|
|
267
|
+
heading1: 'Analytics',
|
|
268
|
+
source_page_url: 'https://huggingface.co/docs/hub/analytics#section1',
|
|
269
|
+
source_page_title: 'Analytics Page',
|
|
270
|
+
heading2: 'Section 1',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
text: 'Second result from section 2',
|
|
274
|
+
product: 'hub',
|
|
275
|
+
heading1: 'Analytics',
|
|
276
|
+
source_page_url: 'https://huggingface.co/docs/hub/analytics#section2',
|
|
277
|
+
source_page_title: 'Analytics Page',
|
|
278
|
+
heading2: 'Section 2',
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
text: 'Third result from section 3',
|
|
282
|
+
product: 'hub',
|
|
283
|
+
heading1: 'Analytics',
|
|
284
|
+
source_page_url: 'https://huggingface.co/docs/hub/analytics#section3',
|
|
285
|
+
source_page_title: 'Analytics Page',
|
|
286
|
+
heading2: 'Section 3',
|
|
287
|
+
},
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
mockFetch.mockResolvedValueOnce({
|
|
291
|
+
ok: true,
|
|
292
|
+
json: () => Promise.resolve(sampleResults),
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const result = await docSearchTool.search({ query: 'analytics' });
|
|
296
|
+
|
|
297
|
+
// All three results should be grouped under one page heading (without anchor)
|
|
298
|
+
expect(result).toContain('### Results from [Analytics](https://huggingface.co/docs/hub/analytics) (3 results)');
|
|
299
|
+
|
|
300
|
+
// All three excerpts should appear under the same page
|
|
301
|
+
expect(result).toContain('First result from section 1');
|
|
302
|
+
expect(result).toContain('Second result from section 2');
|
|
303
|
+
expect(result).toContain('Third result from section 3');
|
|
304
|
+
|
|
305
|
+
// There should only be one "Results from" heading for this page
|
|
306
|
+
const resultsFromCount = (result.match(/### Results from/g) || []).length;
|
|
307
|
+
expect(resultsFromCount).toBe(1);
|
|
261
308
|
});
|
|
262
309
|
|
|
263
310
|
it('should handle API errors gracefully', async () => {
|
|
264
311
|
mockFetch.mockRejectedValueOnce(new Error('Network error'));
|
|
265
312
|
|
|
266
|
-
await expect(docSearchTool.search('test')).rejects.toThrow('Failed to search documentation:');
|
|
313
|
+
await expect(docSearchTool.search({ query: 'test' })).rejects.toThrow('Failed to search documentation:');
|
|
267
314
|
});
|
|
268
315
|
});
|
|
269
316
|
|
|
@@ -298,21 +345,21 @@ describe('DocSearchTool', () => {
|
|
|
298
345
|
json: () => Promise.resolve(sampleResults),
|
|
299
346
|
});
|
|
300
347
|
|
|
301
|
-
const result = await docSearchTool.search('test');
|
|
348
|
+
const result = await docSearchTool.search({ query: 'test' });
|
|
302
349
|
|
|
303
350
|
// Verify grouping structure in output
|
|
304
351
|
expect(result).toContain('## Results for Product: hub');
|
|
305
352
|
expect(result).toContain('## Results for Product: transformers');
|
|
306
|
-
|
|
353
|
+
|
|
307
354
|
// Verify that both results from the same page are together
|
|
308
355
|
const result1Index = result.indexOf('Result 1');
|
|
309
356
|
const result2Index = result.indexOf('Result 2');
|
|
310
357
|
const result3Index = result.indexOf('Result 3');
|
|
311
|
-
|
|
358
|
+
|
|
312
359
|
// Results 1 and 2 should be close together (same page)
|
|
313
360
|
expect(Math.abs(result2Index - result1Index)).toBeLessThan(100);
|
|
314
361
|
// Result 3 should be further away (different product)
|
|
315
362
|
expect(Math.abs(result3Index - result1Index)).toBeGreaterThan(50);
|
|
316
363
|
});
|
|
317
364
|
});
|
|
318
|
-
});
|
|
365
|
+
});
|
|
@@ -4,10 +4,8 @@ import { escapeMarkdown } from '../utilities.js';
|
|
|
4
4
|
import { DOC_FETCH_CONFIG } from './doc-fetch.js';
|
|
5
5
|
|
|
6
6
|
export const DOCS_SEMANTIC_SEARCH_CONFIG = {
|
|
7
|
-
name: '
|
|
8
|
-
description:
|
|
9
|
-
'Search the Hugging Face documentation library with semantic search. Returns documentation excerpts ' +
|
|
10
|
-
'grouped by Product and document page.',
|
|
7
|
+
name: 'hf_doc_search',
|
|
8
|
+
description: 'Search the Hugging Face documentation library. Returns excerpts grouped by Product and Document.',
|
|
11
9
|
schema: z.object({
|
|
12
10
|
query: z
|
|
13
11
|
.string()
|
|
@@ -17,10 +15,12 @@ export const DOCS_SEMANTIC_SEARCH_CONFIG = {
|
|
|
17
15
|
product: z
|
|
18
16
|
.string()
|
|
19
17
|
.optional()
|
|
20
|
-
.describe(
|
|
18
|
+
.describe(
|
|
19
|
+
'Filter by Product (e.g., "hub", "dataset-viewer", "transformers"). Supply when known for focused results'
|
|
20
|
+
),
|
|
21
21
|
}),
|
|
22
22
|
annotations: {
|
|
23
|
-
title: 'Hugging Face Documentation Search',
|
|
23
|
+
title: 'Hugging Face Documentation Library Search',
|
|
24
24
|
destructiveHint: false,
|
|
25
25
|
readOnlyHint: true,
|
|
26
26
|
openWorldHint: true,
|
|
@@ -59,24 +59,24 @@ export class DocSearchTool extends HfApiCall<DocSearchApiParams, DocSearchResult
|
|
|
59
59
|
* @param query Search query string (e.g. "rate limits", "analytics")
|
|
60
60
|
* @param product Optional product filter
|
|
61
61
|
*/
|
|
62
|
-
async search(
|
|
62
|
+
async search(params: DocSearchParams): Promise<string> {
|
|
63
63
|
try {
|
|
64
|
-
if (!query) return 'No query provided';
|
|
64
|
+
if (!params.query) return 'No query provided';
|
|
65
65
|
|
|
66
|
-
const
|
|
67
|
-
if (product) {
|
|
68
|
-
|
|
66
|
+
const apiParams: DocSearchApiParams = { q: params.query.toLowerCase() };
|
|
67
|
+
if (params.product) {
|
|
68
|
+
apiParams.product = params.product;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const results = await this.callApi<DocSearchResult[]>(
|
|
71
|
+
const results = await this.callApi<DocSearchResult[]>(apiParams);
|
|
72
72
|
|
|
73
73
|
if (results.length === 0) {
|
|
74
|
-
return product
|
|
75
|
-
? `No documentation found for query '${query}' in product '${product}'`
|
|
76
|
-
: `No documentation found for query '${query}'`;
|
|
74
|
+
return params.product
|
|
75
|
+
? `No documentation found for query '${params.query}' in product '${params.product}'`
|
|
76
|
+
: `No documentation found for query '${params.query}'`;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
return formatSearchResults(query, results, product);
|
|
79
|
+
return formatSearchResults(params.query, results, params.product);
|
|
80
80
|
} catch (error) {
|
|
81
81
|
if (error instanceof Error) {
|
|
82
82
|
throw new Error(`Failed to search documentation: ${error.message}`);
|
|
@@ -100,11 +100,14 @@ function groupResults(results: DocSearchResult[]): Map<string, Map<string, DocSe
|
|
|
100
100
|
const productGroup = grouped.get(result.product);
|
|
101
101
|
if (!productGroup) continue;
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// Strip the anchor (#section) from the URL for grouping purposes
|
|
104
|
+
const baseUrl = result.source_page_url.split('#')[0] || result.source_page_url;
|
|
105
|
+
|
|
106
|
+
if (!productGroup.has(baseUrl)) {
|
|
107
|
+
productGroup.set(baseUrl, []);
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
const pageResults = productGroup.get(
|
|
110
|
+
const pageResults = productGroup.get(baseUrl);
|
|
108
111
|
if (pageResults) {
|
|
109
112
|
pageResults.push(result);
|
|
110
113
|
}
|
|
@@ -114,23 +117,52 @@ function groupResults(results: DocSearchResult[]): Map<string, Map<string, DocSe
|
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
/**
|
|
117
|
-
*
|
|
120
|
+
* Group page results by section (heading2)
|
|
121
|
+
*/
|
|
122
|
+
function groupBySection(pageResults: DocSearchResult[]): Map<string | undefined, DocSearchResult[]> {
|
|
123
|
+
const sectionGroups = new Map<string | undefined, DocSearchResult[]>();
|
|
124
|
+
|
|
125
|
+
for (const result of pageResults) {
|
|
126
|
+
const section = result.heading2;
|
|
127
|
+
if (!sectionGroups.has(section)) {
|
|
128
|
+
sectionGroups.set(section, []);
|
|
129
|
+
}
|
|
130
|
+
const sectionResults = sectionGroups.get(section);
|
|
131
|
+
if (sectionResults) {
|
|
132
|
+
sectionResults.push(result);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return sectionGroups;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Format excerpts from a section
|
|
118
141
|
*/
|
|
119
|
-
function
|
|
142
|
+
function formatSectionExcerpts(section: string | undefined, results: DocSearchResult[]): string {
|
|
120
143
|
const lines: string[] = [];
|
|
121
144
|
|
|
122
|
-
if
|
|
123
|
-
|
|
145
|
+
// Add section heading if present
|
|
146
|
+
if (section) {
|
|
147
|
+
if (results.length > 1) {
|
|
148
|
+
lines.push(`#### Excerpts from the "${escapeMarkdown(section)}" section`);
|
|
149
|
+
} else {
|
|
150
|
+
lines.push(`#### Excerpt from the "${escapeMarkdown(section)}" section`);
|
|
151
|
+
}
|
|
152
|
+
lines.push('');
|
|
124
153
|
}
|
|
125
154
|
|
|
126
|
-
//
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
.
|
|
130
|
-
|
|
155
|
+
// Add all excerpts from this section
|
|
156
|
+
for (const result of results) {
|
|
157
|
+
// Clean up the text - remove HTML tags if any
|
|
158
|
+
const cleanText = result.text
|
|
159
|
+
.replace(/<[^>]*>/g, '')
|
|
160
|
+
.replace(/\n\s*\n/g, '\n')
|
|
161
|
+
.trim();
|
|
131
162
|
|
|
132
|
-
|
|
133
|
-
|
|
163
|
+
lines.push(cleanText);
|
|
164
|
+
lines.push('');
|
|
165
|
+
}
|
|
134
166
|
|
|
135
167
|
return lines.join('\n');
|
|
136
168
|
}
|
|
@@ -143,7 +175,7 @@ function formatSearchResults(query: string, results: DocSearchResult[], productF
|
|
|
143
175
|
|
|
144
176
|
// Header
|
|
145
177
|
const filterText = productFilter ? ` (filtered by product: ${productFilter})` : '';
|
|
146
|
-
lines.push(`# Documentation Search Results for "${escapeMarkdown(query)}"${filterText}`);
|
|
178
|
+
lines.push(`# Documentation Library Search Results for "${escapeMarkdown(query)}"${filterText}`);
|
|
147
179
|
lines.push('');
|
|
148
180
|
lines.push(`Found ${results.length} results`);
|
|
149
181
|
lines.push('');
|
|
@@ -189,19 +221,24 @@ function formatSearchResults(query: string, results: DocSearchResult[], productF
|
|
|
189
221
|
// Page header with link and hit count
|
|
190
222
|
const pageTitle = firstResult.heading1 || firstResult.source_page_title;
|
|
191
223
|
const hitCount = pageResults.length > 1 ? ` (${pageResults.length} results)` : '';
|
|
224
|
+
// Use the base URL (without anchor) for the page link
|
|
192
225
|
lines.push(`### Results from [${escapeMarkdown(pageTitle)}](${url})${hitCount}`);
|
|
193
226
|
lines.push('');
|
|
194
227
|
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
228
|
+
// Group results by section and format them
|
|
229
|
+
const sectionGroups = groupBySection(pageResults);
|
|
230
|
+
|
|
231
|
+
// Format each section's excerpts
|
|
232
|
+
for (const [section, sectionResults] of sectionGroups) {
|
|
233
|
+
lines.push(formatSectionExcerpts(section, sectionResults));
|
|
198
234
|
}
|
|
199
235
|
}
|
|
200
236
|
}
|
|
201
237
|
|
|
202
238
|
// Add suggestion to use doc fetch tool
|
|
203
239
|
lines.push('---');
|
|
204
|
-
lines.push(
|
|
240
|
+
lines.push('');
|
|
241
|
+
lines.push(`Use the "${DOC_FETCH_CONFIG.name}" tool to fetch a document from the library.`);
|
|
205
242
|
|
|
206
243
|
return lines.join('\n');
|
|
207
244
|
}
|