Skip to main content
Glama
index.ts3.8 kB
import { DuckDuckGoSearcher } from './search.js'; import { GitHubCodeSearcher } from './github-code-search.js'; import { ContentExtractor } from './extractor.js'; import { CLIInterface } from './cli.js'; import { config } from './config.js'; import type { SearchResultsPage, ExtractedContent, Searcher, GitHubCodeSearchOptions } from './types.js'; // Export the interfaces and classes for public use export type { Searcher, SearchResultsPage, SearchStatistics, GitHubCodeSearchOptions } from './types.js'; export { DuckDuckGoSearcher } from './search.js'; export { GitHubCodeSearcher } from './github-code-search.js'; export { RatelimitException, DuckDuckGoSearchException, GitHubSearchException, GitHubAuthException } from './types.js'; export class LLMResearcher { public searcher: Searcher; public extractor: ContentExtractor; public cli: CLIInterface; constructor(searcher?: Searcher) { this.searcher = searcher || new DuckDuckGoSearcher(); this.extractor = new ContentExtractor(); this.cli = new CLIInterface(this); } // Create a new instance with GitHub Code searcher static withGitHubCodeSearch(options?: Partial<GitHubCodeSearchOptions>): LLMResearcher { return new LLMResearcher(new GitHubCodeSearcher(options)); } // Switch to GitHub Code searcher useGitHubCodeSearch(options?: Partial<GitHubCodeSearchOptions>): void { this.searcher = new GitHubCodeSearcher(options); } // Switch to DuckDuckGo searcher useDuckDuckGoSearch(): void { this.searcher = new DuckDuckGoSearcher(); } // Get the current searcher type getSearcherType(): string { if (this.searcher instanceof GitHubCodeSearcher) { return 'GitHub Code Search'; } else if (this.searcher instanceof DuckDuckGoSearcher) { return 'DuckDuckGo'; } return 'Unknown'; } async search(query: string, nextToken?: string, options?: import('./types.js').SearchOptions): Promise<SearchResultsPage> { config.log(`Starting search for: ${query}`); return await this.searcher.search(query, nextToken, options); } async extractFromUrl(url: string, displayOutput = true): Promise<ExtractedContent> { config.log(`Extracting content from: ${url}`); try { const content = await this.extractor.extract(url); if (displayOutput) { this.cli.displayContent(content); // Only start interactive commands if we're in interactive mode if (process.stdin.isTTY) { await this.cli.handleContentCommands(content); } } return content; } catch (error) { const message = `Failed to extract content from ${url}: ${(error as Error).message}`; if (displayOutput) { console.error(message); } throw new Error(message); } } async interactive(): Promise<void> { await this.cli.interactive(); await this.cleanup(); } async cleanup(): Promise<void> { config.log('Cleaning up resources...'); await this.extractor.close(); } async searchAndDisplay(query: string): Promise<void> { try { const searchPage = await this.search(query); if (searchPage.results.length === 0) { console.log('No results found.'); return; } this.cli.currentResults = searchPage.results; this.cli.currentPage = searchPage; this.cli.displayResults(searchPage); await this.cli.handleResultSelection(); } catch (error) { console.error('Search failed:', (error as Error).message); } finally { await this.cleanup(); } } } // Handle process termination process.on('SIGINT', async () => { console.log('\nShutting down...'); process.exit(0); }); process.on('SIGTERM', async () => { console.log('\nShutting down...'); process.exit(0); });

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/Code-Hex/light-research-mcp'

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