Skip to main content
Glama
knowledgeBaseApi.ts7.8 kB
import { Router } from 'express'; import { z } from 'zod'; import path from 'path'; import { RepositoryManager } from '../core/repositoryManager'; import { LLMService } from '../orchestrator/llmService'; import { validateRequest } from './middleware/validation'; import { KnowledgeBaseService } from '../knowledge-base/knowledgeBaseService'; import { TimelineService } from '../core/timelineService'; import { SearchService } from '../search/searchService'; /** * Creates and configures the knowledge base API router */ export function createKnowledgeBaseApi( repositoryManager: RepositoryManager, llmService: LLMService ): Router { const router = Router(); // Create timeline service and knowledge base service const timelineService = new TimelineService(); const searchService = new SearchService(repositoryManager); const knowledgeBaseService = new KnowledgeBaseService(llmService, timelineService, searchService); // Schema for repository ID parameter const repoIdParamSchema = z.object({ repositoryId: z.string().uuid() }); // Schema for topic path parameter const topicPathParamSchema = z.object({ repositoryId: z.string().uuid(), topicPath: z.string() }); // Schema for generate knowledge base request const generateKnowledgeBaseSchema = z.object({ forceRegenerate: z.boolean().optional() }); /** * Generate or update the knowledge base for a repository * POST /api/knowledge-base/:repositoryId/generate */ router.post( '/:repositoryId/generate', validateRequest({ params: repoIdParamSchema, body: generateKnowledgeBaseSchema }), async (req, res, next) => { try { const { repositoryId } = req.params; const { forceRegenerate } = req.body; const repository = repositoryManager.getRepository(repositoryId); // Check if repository implements listFiles if (typeof repository.listFiles !== 'function' || repository.listFiles.toString().includes('throw new Error(\'Method not implemented\')')) { return res.status(500).json({ error: 'Repository implementation error', message: 'The repository does not properly implement the listFiles method' }); } const fileInfos = await repository.listFiles(); // Filter out non-text files and ensure we only process files from the 'raw/' directory const rawTextFiles = fileInfos.filter(file => { const filePath = typeof file.path === 'string' ? file.path : ''; const ext = path.extname(filePath).toLowerCase(); return filePath.startsWith('raw/') && !filePath.endsWith('/') && // Exclude directories !filePath.includes('.lspace/') && // Exclude metadata files filePath !== 'raw/.gitkeep' && // Exclude .gitkeep files ['.md', '.txt', '.json', '.yaml', '.yml', '.html', '.xml'].includes(ext); }); if (rawTextFiles.length === 0) { return res.status(400).json({ error: 'No suitable documents', message: 'No text documents found in the raw/ directory matching the allowed extensions.' }); } // Use the KnowledgeBaseService to generate the knowledge base try { console.log(`Generating knowledge base for repository ${repositoryId} with ${rawTextFiles.length} files`); // Call the KnowledgeBaseService with appropriate options await knowledgeBaseService.OLD_generateKnowledgeBase(repository); // Create a marker file to indicate generation completed const markerFilePath = path.join('.lspace', 'kb_generated.marker'); await repository.writeFile(markerFilePath, `KB generated at ${new Date().toISOString()} for ${rawTextFiles.length} files.`); await repository.add([markerFilePath]); await repository.commit({ message: 'Generate/Update knowledge base' }); res.status(200).json({ message: 'Knowledge base generation triggered successfully.', processedFiles: rawTextFiles.length }); } catch (kbError: any) { console.error('Error generating knowledge base:', kbError); return res.status(500).json({ error: 'Knowledge base generation failed', message: kbError.message || 'An error occurred during knowledge base generation' }); } } catch (error) { next(error); } } ); /** * Get the entry page for a repository's knowledge base * GET /api/knowledge-base/:repositoryId/entry */ router.get( '/:repositoryId/entry', validateRequest({ params: repoIdParamSchema }), async (req, res, next) => { try { const { repositoryId } = req.params; // Get the repository const repository = repositoryManager.getRepository(repositoryId); // Check if the entry page exists const entryPageExists = await repository.fileExists('knowledge-base/index.md'); if (!entryPageExists) { return res.status(404).json({ error: 'Knowledge base not found' }); } // Read the entry page const content = await repository.readFile('knowledge-base/index.md'); res.setHeader('Content-Type', 'text/markdown'); res.send(content); } catch (error) { next(error); } } ); /** * Get a specific topic page from the knowledge base * GET /api/knowledge-base/:repositoryId/topics/:topicPath */ router.get( '/:repositoryId/topics/:topicPath', validateRequest({ params: topicPathParamSchema }), async (req, res, next) => { try { const { repositoryId, topicPath } = req.params; // Get the repository const repository = repositoryManager.getRepository(repositoryId); // Check if the topic page exists const topicPageExists = await repository.fileExists(`knowledge-base/${topicPath}.md`); if (!topicPageExists) { return res.status(404).json({ error: 'Topic not found' }); } // Read the topic page const content = await repository.readFile(`knowledge-base/${topicPath}.md`); res.setHeader('Content-Type', 'text/markdown'); res.send(content); } catch (error) { next(error); } } ); /** * List all topics in the knowledge base * GET /api/knowledge-base/:repositoryId/topics */ router.get( '/:repositoryId/topics', validateRequest({ params: repoIdParamSchema }), async (req, res, next) => { try { const { repositoryId } = req.params; // Get the repository const repository = repositoryManager.getRepository(repositoryId); // Check if the knowledge base exists const knowledgeBaseExists = await repository.fileExists('knowledge-base/index.md'); if (!knowledgeBaseExists) { return res.status(404).json({ error: 'Knowledge base not found' }); } // List all topic files const files = await repository.listFiles(); const topicFiles = files.filter(file => file.path.startsWith('knowledge-base/') && file.path !== 'knowledge-base/index.md' && file.path.endsWith('.md') ); // Extract topic information const topics = topicFiles.map(file => ({ path: file.path.replace('knowledge-base/', '').replace('.md', ''), title: file.path.split('/').pop()?.replace('.md', '') || '' })); res.json(topics); } catch (error) { next(error); } } ); return router; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Lspace-io/lspace-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server