UNPKG

codecanon

Version:

CLI tool that downloads documentation from 3rd party libraries, converts them to Markdown, and optimizes for LLMs

79 lines (75 loc) 3.21 kB
import { promises as fs } from "fs"; import { join } from "path"; import { getWorkspacePaths, isWorkspaceInitialized, loadWorkspaceConfig, } from "./workspace.js"; /** * Query the local documentation context using natural language */ export async function queryContext(options) { // Ensure workspace is initialized if (!(await isWorkspaceInitialized(options.cwd))) { throw new Error("No CodeCanon workspace found. Run 'canon init' first."); } const config = await loadWorkspaceConfig(options.cwd); if (config.packages.length === 0) { throw new Error("No packages in workspace. Use 'canon add <package>' to add documentation first."); } // Filter packages if specified const targetPackages = options.packages ? config.packages.filter((p) => options.packages.includes(p.name)) : config.packages; if (targetPackages.length === 0) { throw new Error("No matching packages found in workspace."); } // TODO: Implement actual LLM querying with RAG // For now, return a placeholder response const contextChunks = await loadRelevantContext(options, targetPackages); const answer = await generateAnswer(options, contextChunks); return { answer, sources: contextChunks.map((chunk) => ({ package: chunk.package, section: chunk.section, url: chunk.url, })), }; } /** * Load relevant context chunks for the query (placeholder implementation) */ async function loadRelevantContext(options, packages) { const paths = getWorkspacePaths(options.cwd); const chunks = []; // TODO: Implement vector similarity search // For now, just load some content from each package for (const pkg of packages.slice(0, options.contextLimit)) { try { const chunkPath = join(paths.cache, pkg.name, pkg.version, "chunks", "README.chunk.md"); const content = await fs.readFile(chunkPath, "utf-8"); chunks.push({ package: pkg.name, section: "README", content: content.slice(0, 1000), // Limit content length url: pkg.documentationUrl, }); } catch (error) { console.warn(`Warning: Could not load content for ${pkg.name}`); } } return chunks; } /** * Generate an answer using the context chunks (placeholder implementation) */ async function generateAnswer(options, contextChunks) { // TODO: Implement actual LLM API calls // For now, return a mock response that incorporates the context const packageNames = contextChunks.map((c) => c.package).join(", "); return `This is a placeholder answer for your question: "${options.question}" Based on the documentation for packages: ${packageNames} The actual LLM integration will be implemented later. This would normally: 1. Use the selected model (${options.model || "default"}) 2. Include relevant context from ${contextChunks.length} documentation chunks 3. Generate a comprehensive answer using RAG (Retrieval-Augmented Generation) Context loaded from: ${contextChunks.map((c) => `${c.package}/${c.section}`).join(", ")}`; }