/** * query-docs tool handler * * Fetches documentation and code examples from TrueRef for a specific library. * Tool schema is identical to context7 for drop-in compatibility. */ import { z } from 'zod'; import { fetchContext } from '../client.js'; export const QueryDocsSchema = z.object({ libraryId: z .string() .describe('The TrueRef library ID obtained from resolve-library-id, e.g. /facebook/react'), query: z .string() .describe('Specific question about the library to retrieve relevant documentation'), tokens: z.number().optional().describe('Maximum token budget for the response (default: 10000)'), searchMode: z .enum(['auto', 'keyword', 'semantic', 'hybrid']) .optional() .describe( "Retrieval mode: 'auto' (default), 'keyword' (FTS only), 'semantic' (vector only), or 'hybrid'" ), alpha: z .number() .min(0) .max(1) .optional() .describe('Hybrid blend weight: 0.0 = keyword only, 1.0 = semantic only (default: 0.5)') }); export type QueryDocsInput = z.infer; export const QUERY_DOCS_TOOL = { name: 'query-docs', description: [ 'Fetches documentation and code examples from TrueRef for a specific library.', 'Requires a library ID obtained from resolve-library-id.', 'Returns relevant snippets formatted for LLM consumption.', 'Call at most 3 times per user question.' ].join(' '), inputSchema: { type: 'object' as const, properties: { libraryId: { type: 'string', description: 'TrueRef library ID, e.g. /facebook/react' }, query: { type: 'string', description: 'Specific question about the library' }, tokens: { type: 'number', description: 'Max token budget (default: 10000)' }, searchMode: { type: 'string', enum: ['auto', 'keyword', 'semantic', 'hybrid'], description: "Retrieval mode: 'auto' (default), 'keyword', 'semantic', or 'hybrid'" }, alpha: { type: 'number', minimum: 0, maximum: 1, description: 'Hybrid blend weight (0=keyword, 1=semantic, default: 0.5)' } }, required: ['libraryId', 'query'] } }; export async function handleQueryDocs(args: unknown) { const { libraryId, query, tokens, searchMode, alpha } = QueryDocsSchema.parse(args); const response = await fetchContext({ libraryId, query, tokens, type: 'txt', searchMode, alpha }); if (!response.ok) { const status = response.status; if (status === 404) { return { content: [ { type: 'text' as const, text: `Library "${libraryId}" not found. Please run resolve-library-id first.` } ], isError: true }; } if (status === 503) { return { content: [ { type: 'text' as const, text: `Library "${libraryId}" is currently being indexed. Please try again in a moment.` } ], isError: true }; } return { content: [ { type: 'text' as const, text: `Error fetching documentation: ${response.status} ${response.statusText}` } ], isError: true }; } const text = await response.text(); return { content: [{ type: 'text' as const, text }] }; }