Add source field to search results and clean up unused code
Updates search functionality to include source field in results, adds Editor documentation search handler, and removes unused helper methods from TSX parser. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
005a17f345
commit
5483eedcc2
@ -34,7 +34,8 @@ describe('MCP_SERVER_CONFIG', () => {
|
|||||||
expect(tools).toContain('search_babylon_api');
|
expect(tools).toContain('search_babylon_api');
|
||||||
expect(tools).toContain('search_babylon_source');
|
expect(tools).toContain('search_babylon_source');
|
||||||
expect(tools).toContain('get_babylon_source');
|
expect(tools).toContain('get_babylon_source');
|
||||||
expect(tools.length).toBe(5);
|
expect(tools).toContain('search_babylon_editor_docs');
|
||||||
|
expect(tools.length).toBe(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should define prompts capability', () => {
|
it('should define prompts capability', () => {
|
||||||
@ -61,6 +62,7 @@ describe('MCP_SERVER_CONFIG', () => {
|
|||||||
expect(instructions).toContain('search_babylon_api');
|
expect(instructions).toContain('search_babylon_api');
|
||||||
expect(instructions).toContain('search_babylon_source');
|
expect(instructions).toContain('search_babylon_source');
|
||||||
expect(instructions).toContain('get_babylon_source');
|
expect(instructions).toContain('get_babylon_source');
|
||||||
|
expect(instructions).toContain('search_babylon_editor_docs');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -12,13 +12,14 @@ export const MCP_SERVER_CONFIG = {
|
|||||||
capabilities: {
|
capabilities: {
|
||||||
tools: {
|
tools: {
|
||||||
description:
|
description:
|
||||||
'Provides tools for searching and retrieving Babylon.js documentation, API references, and source code',
|
'Provides tools for searching and retrieving Babylon.js documentation, API references, source code, and Editor documentation',
|
||||||
available: [
|
available: [
|
||||||
'search_babylon_docs',
|
'search_babylon_docs',
|
||||||
'get_babylon_doc',
|
'get_babylon_doc',
|
||||||
'search_babylon_api',
|
'search_babylon_api',
|
||||||
'search_babylon_source',
|
'search_babylon_source',
|
||||||
'get_babylon_source',
|
'get_babylon_source',
|
||||||
|
'search_babylon_editor_docs',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
prompts: {
|
prompts: {
|
||||||
@ -32,13 +33,14 @@ export const MCP_SERVER_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
instructions:
|
instructions:
|
||||||
'Babylon MCP Server provides access to Babylon.js documentation, API references, and source code. ' +
|
'Babylon MCP Server provides access to Babylon.js documentation, API references, source code, and Editor documentation. ' +
|
||||||
'Available tools:\n' +
|
'Available tools:\n' +
|
||||||
'- search_babylon_docs: Search documentation with optional category filtering\n' +
|
'- search_babylon_docs: Search documentation with optional category filtering\n' +
|
||||||
'- get_babylon_doc: Retrieve full documentation page by path\n' +
|
'- get_babylon_doc: Retrieve full documentation page by path\n' +
|
||||||
'- search_babylon_api: Search API documentation (classes, methods, properties)\n' +
|
'- search_babylon_api: Search API documentation (classes, methods, properties)\n' +
|
||||||
'- search_babylon_source: Search Babylon.js source code files with optional package filtering\n' +
|
'- search_babylon_source: Search Babylon.js source code files with optional package filtering\n' +
|
||||||
'- get_babylon_source: Retrieve source file content with optional line range\n' +
|
'- get_babylon_source: Retrieve source file content with optional line range\n' +
|
||||||
|
'- search_babylon_editor_docs: Search Babylon.js Editor documentation for tool usage and workflows\n' +
|
||||||
'This server helps reduce token usage by providing a canonical source for Babylon.js framework information.',
|
'This server helps reduce token usage by providing a canonical source for Babylon.js framework information.',
|
||||||
|
|
||||||
transport: {
|
transport: {
|
||||||
@ -62,6 +64,10 @@ export const MCP_SERVER_CONFIG = {
|
|||||||
repository: 'https://github.com/BabylonJS/havok.git',
|
repository: 'https://github.com/BabylonJS/havok.git',
|
||||||
description: 'Havok Physics integration',
|
description: 'Havok Physics integration',
|
||||||
},
|
},
|
||||||
|
editor: {
|
||||||
|
repository: 'https://github.com/BabylonJS/Editor.git',
|
||||||
|
description: 'Babylon.js Editor tool and documentation',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ describe('MCP Handlers', () => {
|
|||||||
it('should register all required tools', () => {
|
it('should register all required tools', () => {
|
||||||
setupHandlers(mockServer);
|
setupHandlers(mockServer);
|
||||||
|
|
||||||
expect(registerToolSpy).toHaveBeenCalledTimes(5);
|
expect(registerToolSpy).toHaveBeenCalledTimes(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register search_babylon_docs tool', () => {
|
it('should register search_babylon_docs tool', () => {
|
||||||
@ -251,6 +251,69 @@ describe('MCP Handlers', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('search_babylon_editor_docs handler', () => {
|
||||||
|
let editorSearchHandler: (params: unknown) => Promise<unknown>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setupHandlers(mockServer);
|
||||||
|
editorSearchHandler = registerToolSpy.mock.calls[5]![2];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept required query parameter', async () => {
|
||||||
|
const params = { query: 'attaching scripts' };
|
||||||
|
const result = (await editorSearchHandler(params)) as { content: { type: string; text: string }[] };
|
||||||
|
|
||||||
|
expect(result).toHaveProperty('content');
|
||||||
|
expect(Array.isArray(result.content)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept optional category parameter', async () => {
|
||||||
|
const params = { query: 'lifecycle', category: 'scripting' };
|
||||||
|
const result = (await editorSearchHandler(params)) as { content: unknown[] };
|
||||||
|
|
||||||
|
expect(result).toHaveProperty('content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept optional limit parameter', async () => {
|
||||||
|
const params = { query: 'editor', limit: 10 };
|
||||||
|
const result = (await editorSearchHandler(params)) as { content: unknown[] };
|
||||||
|
|
||||||
|
expect(result).toHaveProperty('content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should default limit to 5 when not provided', async () => {
|
||||||
|
const params = { query: 'project' };
|
||||||
|
const result = (await editorSearchHandler(params)) as { content: { type: string; text: string }[] };
|
||||||
|
|
||||||
|
const responseText = result.content[0]!.text;
|
||||||
|
expect(responseText.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return text content type', async () => {
|
||||||
|
const params = { query: 'scripts' };
|
||||||
|
const result = (await editorSearchHandler(params)) as { content: { type: string; text: string }[] };
|
||||||
|
|
||||||
|
expect(result.content[0]).toHaveProperty('type', 'text');
|
||||||
|
expect(result.content[0]).toHaveProperty('text');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return JSON-parseable response or no results message', async () => {
|
||||||
|
const params = { query: 'editor features' };
|
||||||
|
const result = (await editorSearchHandler(params)) as { content: { type: string; text: string }[] };
|
||||||
|
|
||||||
|
const responseText = result.content[0]!.text;
|
||||||
|
// Response may be "No Editor documentation found" or valid JSON
|
||||||
|
if (!responseText.startsWith('No Editor documentation')) {
|
||||||
|
expect(() => JSON.parse(responseText)).not.toThrow();
|
||||||
|
const parsed = JSON.parse(responseText);
|
||||||
|
expect(parsed).toHaveProperty('query');
|
||||||
|
expect(parsed).toHaveProperty('source', 'editor-docs');
|
||||||
|
expect(parsed).toHaveProperty('totalResults');
|
||||||
|
expect(parsed).toHaveProperty('results');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Tool Schemas', () => {
|
describe('Tool Schemas', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setupHandlers(mockServer);
|
setupHandlers(mockServer);
|
||||||
@ -292,6 +355,14 @@ describe('MCP Handlers', () => {
|
|||||||
expect(toolConfig.inputSchema).toHaveProperty('startLine');
|
expect(toolConfig.inputSchema).toHaveProperty('startLine');
|
||||||
expect(toolConfig.inputSchema).toHaveProperty('endLine');
|
expect(toolConfig.inputSchema).toHaveProperty('endLine');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('search_babylon_editor_docs should have proper schema structure', () => {
|
||||||
|
const toolConfig = registerToolSpy.mock.calls[5]![1];
|
||||||
|
|
||||||
|
expect(toolConfig.inputSchema).toHaveProperty('query');
|
||||||
|
expect(toolConfig.inputSchema).toHaveProperty('category');
|
||||||
|
expect(toolConfig.inputSchema).toHaveProperty('limit');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search_babylon_source handler', () => {
|
describe('search_babylon_source handler', () => {
|
||||||
|
|||||||
188
src/mcp/handlers/editor/search-editor-docs.handler.test.ts
Normal file
188
src/mcp/handlers/editor/search-editor-docs.handler.test.ts
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||||
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||||
|
import * as searchEditorDocsHandler from './search-editor-docs.handler.js';
|
||||||
|
import * as searchInstance from '../shared/search-instance.js';
|
||||||
|
|
||||||
|
vi.mock('../shared/search-instance.js', () => ({
|
||||||
|
getSearchInstance: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('search-editor-docs.handler', () => {
|
||||||
|
let mockServer: McpServer;
|
||||||
|
let mockSearch: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockServer = {
|
||||||
|
registerTool: vi.fn(),
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
mockSearch = {
|
||||||
|
search: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
vi.mocked(searchInstance.getSearchInstance).mockResolvedValue(mockSearch);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('register', () => {
|
||||||
|
it('should register search_babylon_editor_docs tool with correct metadata', () => {
|
||||||
|
searchEditorDocsHandler.register(mockServer);
|
||||||
|
|
||||||
|
expect(mockServer.registerTool).toHaveBeenCalledWith(
|
||||||
|
'search_babylon_editor_docs',
|
||||||
|
expect.objectContaining({
|
||||||
|
description:
|
||||||
|
'Search Babylon.js Editor documentation for tool usage, workflows, and features',
|
||||||
|
inputSchema: expect.any(Object),
|
||||||
|
}),
|
||||||
|
expect.any(Function)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should define input schema with query, category, and limit', () => {
|
||||||
|
searchEditorDocsHandler.register(mockServer);
|
||||||
|
|
||||||
|
const callArgs = vi.mocked(mockServer.registerTool).mock.calls[0];
|
||||||
|
const schema = callArgs![1];
|
||||||
|
|
||||||
|
expect(schema.inputSchema).toHaveProperty('query');
|
||||||
|
expect(schema.inputSchema).toHaveProperty('category');
|
||||||
|
expect(schema.inputSchema).toHaveProperty('limit');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handler execution', () => {
|
||||||
|
let handler: Function;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
searchEditorDocsHandler.register(mockServer);
|
||||||
|
const callArgs = vi.mocked(mockServer.registerTool).mock.calls[0];
|
||||||
|
handler = callArgs![2];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should search with query and filter to editor-docs source', async () => {
|
||||||
|
mockSearch.search.mockResolvedValue([
|
||||||
|
{
|
||||||
|
title: 'Adding Scripts',
|
||||||
|
description: 'Learn to attach scripts',
|
||||||
|
content: 'Scripts can be attached...',
|
||||||
|
url: 'https://editor.babylonjs.com/documentation/adding-scripts',
|
||||||
|
category: 'editor/adding-scripts',
|
||||||
|
source: 'editor-docs',
|
||||||
|
score: 0.95,
|
||||||
|
keywords: ['scripts', 'editor'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Vector3 Class',
|
||||||
|
description: 'Core documentation',
|
||||||
|
content: 'Vector3 is...',
|
||||||
|
url: 'https://doc.babylonjs.com/typedoc/classes/Vector3',
|
||||||
|
category: 'api',
|
||||||
|
source: 'documentation',
|
||||||
|
score: 0.85,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await handler({ query: 'scripts' });
|
||||||
|
|
||||||
|
expect(result.content[0].text).toContain('Adding Scripts');
|
||||||
|
expect(result.content[0].text).not.toContain('Vector3');
|
||||||
|
expect(result.content[0].text).toContain('editor-docs');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply category filter with editor/ prefix', async () => {
|
||||||
|
mockSearch.search.mockResolvedValue([
|
||||||
|
{
|
||||||
|
title: 'Customizing Scripts',
|
||||||
|
description: 'Advanced scripting',
|
||||||
|
content: 'Customize your scripts...',
|
||||||
|
url: 'https://editor.babylonjs.com/documentation/scripting/customizing-scripts',
|
||||||
|
category: 'editor/scripting',
|
||||||
|
source: 'editor-docs',
|
||||||
|
score: 0.92,
|
||||||
|
keywords: ['scripting', 'editor'],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await handler({
|
||||||
|
query: 'lifecycle',
|
||||||
|
category: 'scripting',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockSearch.search).toHaveBeenCalledWith('lifecycle', {
|
||||||
|
category: 'editor/scripting',
|
||||||
|
limit: 5,
|
||||||
|
});
|
||||||
|
expect(result.content[0].text).toContain('Customizing Scripts');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respect limit parameter', async () => {
|
||||||
|
mockSearch.search.mockResolvedValue([
|
||||||
|
{
|
||||||
|
title: 'Doc 1',
|
||||||
|
description: 'Description',
|
||||||
|
content: 'Content',
|
||||||
|
url: 'https://editor.babylonjs.com/doc1',
|
||||||
|
category: 'editor',
|
||||||
|
source: 'editor-docs',
|
||||||
|
score: 0.9,
|
||||||
|
keywords: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await handler({ query: 'test', limit: 3 });
|
||||||
|
|
||||||
|
expect(mockSearch.search).toHaveBeenCalledWith('test', { limit: 9 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return no results message when no editor docs found', async () => {
|
||||||
|
mockSearch.search.mockResolvedValue([
|
||||||
|
{
|
||||||
|
title: 'Non-editor doc',
|
||||||
|
description: 'Regular doc',
|
||||||
|
content: 'Content',
|
||||||
|
url: 'https://doc.babylonjs.com/test',
|
||||||
|
category: 'api',
|
||||||
|
source: 'documentation',
|
||||||
|
score: 0.8,
|
||||||
|
keywords: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await handler({ query: 'nonexistent' });
|
||||||
|
|
||||||
|
expect(result.content[0].text).toContain('No Editor documentation found');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should format results with rank, relevance, and snippet', async () => {
|
||||||
|
mockSearch.search.mockResolvedValue([
|
||||||
|
{
|
||||||
|
title: 'Creating Project',
|
||||||
|
description: 'Start a new project',
|
||||||
|
content: 'To create a project...',
|
||||||
|
url: 'https://editor.babylonjs.com/documentation/creating-project',
|
||||||
|
category: 'editor/creating-project',
|
||||||
|
source: 'editor-docs',
|
||||||
|
score: 0.95,
|
||||||
|
keywords: ['project', 'editor'],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await handler({ query: 'project' });
|
||||||
|
const resultText = result.content[0].text;
|
||||||
|
|
||||||
|
expect(resultText).toContain('"rank": 1');
|
||||||
|
expect(resultText).toContain('"title": "Creating Project"');
|
||||||
|
expect(resultText).toContain('"relevance": "95.0%"');
|
||||||
|
expect(resultText).toContain('"snippet": "To create a project..."');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle search errors gracefully', async () => {
|
||||||
|
mockSearch.search.mockRejectedValue(new Error('Search failed'));
|
||||||
|
|
||||||
|
const result = await handler({ query: 'test' });
|
||||||
|
|
||||||
|
expect(result.content[0].text).toContain('Error');
|
||||||
|
expect(result.content[0].text).toContain('Search failed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
73
src/mcp/handlers/editor/search-editor-docs.handler.ts
Normal file
73
src/mcp/handlers/editor/search-editor-docs.handler.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { getSearchInstance } from '../shared/search-instance.js';
|
||||||
|
import {
|
||||||
|
formatJsonResponse,
|
||||||
|
formatNoResultsResponse,
|
||||||
|
} from '../shared/response-formatters.js';
|
||||||
|
import { withErrorHandling } from '../shared/error-handlers.js';
|
||||||
|
|
||||||
|
export function register(server: McpServer): void {
|
||||||
|
server.registerTool(
|
||||||
|
'search_babylon_editor_docs',
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'Search Babylon.js Editor documentation for tool usage, workflows, and features',
|
||||||
|
inputSchema: {
|
||||||
|
query: z
|
||||||
|
.string()
|
||||||
|
.describe('Search query for Editor documentation'),
|
||||||
|
category: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
'Optional category filter (e.g., "scripting", "advanced", "tips")'
|
||||||
|
),
|
||||||
|
limit: z
|
||||||
|
.number()
|
||||||
|
.optional()
|
||||||
|
.default(5)
|
||||||
|
.describe('Maximum number of results to return (default: 5)'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
withErrorHandling(
|
||||||
|
async ({ query, category, limit = 5 }) => {
|
||||||
|
const search = await getSearchInstance();
|
||||||
|
|
||||||
|
// Search with higher limit to ensure we get enough Editor results
|
||||||
|
const searchLimit = category ? limit : limit * 3;
|
||||||
|
const options = category ? { category: `editor/${category}`, limit: searchLimit } : { limit: searchLimit };
|
||||||
|
const results = await search.search(query, options);
|
||||||
|
|
||||||
|
// Filter to only Editor documentation (source = 'editor-docs')
|
||||||
|
const editorResults = results
|
||||||
|
.filter((r: any) => r.source === 'editor-docs')
|
||||||
|
.slice(0, limit);
|
||||||
|
|
||||||
|
if (editorResults.length === 0) {
|
||||||
|
return formatNoResultsResponse(query, 'Editor documentation');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format results for better readability
|
||||||
|
const formattedResults = editorResults.map((result: any, index: number) => ({
|
||||||
|
rank: index + 1,
|
||||||
|
title: result.title,
|
||||||
|
description: result.description,
|
||||||
|
url: result.url,
|
||||||
|
category: result.category,
|
||||||
|
relevance: (result.score * 100).toFixed(1) + '%',
|
||||||
|
snippet: result.content,
|
||||||
|
keywords: result.keywords,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return formatJsonResponse({
|
||||||
|
query,
|
||||||
|
source: 'editor-docs',
|
||||||
|
totalResults: editorResults.length,
|
||||||
|
results: formattedResults,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
'searching Editor documentation'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -4,16 +4,18 @@ import * as getDocHandler from './docs/get-doc.handler.js';
|
|||||||
import * as searchApiHandler from './api/search-api.handler.js';
|
import * as searchApiHandler from './api/search-api.handler.js';
|
||||||
import * as searchSourceHandler from './source/search-source.handler.js';
|
import * as searchSourceHandler from './source/search-source.handler.js';
|
||||||
import * as getSourceHandler from './source/get-source.handler.js';
|
import * as getSourceHandler from './source/get-source.handler.js';
|
||||||
|
import * as searchEditorDocsHandler from './editor/search-editor-docs.handler.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register all MCP tool handlers with the server.
|
* Register all MCP tool handlers with the server.
|
||||||
*
|
*
|
||||||
* This function sets up all 5 Babylon.js MCP tools:
|
* This function sets up all 6 Babylon.js MCP tools:
|
||||||
* - search_babylon_docs: Search documentation
|
* - search_babylon_docs: Search documentation
|
||||||
* - get_babylon_doc: Get specific documentation
|
* - get_babylon_doc: Get specific documentation
|
||||||
* - search_babylon_api: Search API documentation
|
* - search_babylon_api: Search API documentation
|
||||||
* - search_babylon_source: Search source code
|
* - search_babylon_source: Search source code
|
||||||
* - get_babylon_source: Get source code files
|
* - get_babylon_source: Get source code files
|
||||||
|
* - search_babylon_editor_docs: Search Editor documentation
|
||||||
*/
|
*/
|
||||||
export function setupHandlers(server: McpServer): void {
|
export function setupHandlers(server: McpServer): void {
|
||||||
searchDocsHandler.register(server);
|
searchDocsHandler.register(server);
|
||||||
@ -21,4 +23,5 @@ export function setupHandlers(server: McpServer): void {
|
|||||||
searchApiHandler.register(server);
|
searchApiHandler.register(server);
|
||||||
searchSourceHandler.register(server);
|
searchSourceHandler.register(server);
|
||||||
getSourceHandler.register(server);
|
getSourceHandler.register(server);
|
||||||
|
searchEditorDocsHandler.register(server);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export class LanceDBSearch {
|
|||||||
content: this.extractRelevantSnippet(doc.content, query),
|
content: this.extractRelevantSnippet(doc.content, query),
|
||||||
url: doc.url,
|
url: doc.url,
|
||||||
category: doc.category,
|
category: doc.category,
|
||||||
|
source: doc.source,
|
||||||
score: doc._distance ? 1 - doc._distance : 0, // Convert distance to similarity score
|
score: doc._distance ? 1 - doc._distance : 0, // Convert distance to similarity score
|
||||||
keywords: doc.keywords.split(', ').filter(Boolean),
|
keywords: doc.keywords.split(', ').filter(Boolean),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export class TsxParser {
|
|||||||
/**
|
/**
|
||||||
* Parse a TSX file and extract documentation content
|
* Parse a TSX file and extract documentation content
|
||||||
*/
|
*/
|
||||||
async parseFile(filePath: string, urlPrefix: string): Promise<DocumentMetadata> {
|
async parseFile(filePath: string, _urlPrefix: string): Promise<DocumentMetadata> {
|
||||||
const content = await fs.readFile(filePath, 'utf-8');
|
const content = await fs.readFile(filePath, 'utf-8');
|
||||||
|
|
||||||
// Parse TSX file to AST using TypeScript Compiler API
|
// Parse TSX file to AST using TypeScript Compiler API
|
||||||
@ -144,7 +144,7 @@ export class TsxParser {
|
|||||||
/**
|
/**
|
||||||
* Extract code blocks from CodeBlock components and template literals
|
* Extract code blocks from CodeBlock components and template literals
|
||||||
*/
|
*/
|
||||||
private extractCodeBlocksFromAST(sourceFile: ts.SourceFile, content: string): CodeBlock[] {
|
private extractCodeBlocksFromAST(sourceFile: ts.SourceFile, _content: string): CodeBlock[] {
|
||||||
const blocks: CodeBlock[] = [];
|
const blocks: CodeBlock[] = [];
|
||||||
const codeVariables = new Map<string, string>();
|
const codeVariables = new Map<string, string>();
|
||||||
|
|
||||||
@ -328,29 +328,6 @@ export class TsxParser {
|
|||||||
.map(([word]) => word);
|
.map(([word]) => word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean text by removing extra whitespace and decoding HTML entities
|
|
||||||
*/
|
|
||||||
private cleanText(text: string): string {
|
|
||||||
return text
|
|
||||||
.replace(/\s+/g, ' ')
|
|
||||||
.replace(/ /g, ' ')
|
|
||||||
.replace(/"/g, '"')
|
|
||||||
.replace(/'/g, "'")
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if text looks like code or import statement
|
|
||||||
*/
|
|
||||||
private isCodeOrImport(text: string): boolean {
|
|
||||||
return /^(import|export|const|let|var|function|class|interface|type)\s/.test(text.trim()) ||
|
|
||||||
/^[A-Z][a-zA-Z]+Component$/.test(text.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if text looks like code
|
* Check if text looks like code
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -42,6 +42,7 @@ export interface SearchResult {
|
|||||||
content: string;
|
content: string;
|
||||||
url: string;
|
url: string;
|
||||||
category: string;
|
category: string;
|
||||||
|
source: string;
|
||||||
score: number;
|
score: number;
|
||||||
keywords: string[];
|
keywords: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user