@masuidrive/bloom-local-rag
Version:
RAG (Retrieval-Augmented Generation) system for local directories - Index and search your documents with AI-powered answers
101 lines (98 loc) • 4.66 kB
JavaScript
// Suppress LanceDB debug logs unless explicitly enabled
if (!process.env.RUST_LOG) {
// Set general log level to error and specifically disable lance_encoding TRACE logs
process.env.RUST_LOG = 'error,lance_encoding=off,lance_file=off,lance=warn';
}
// Also try LanceDB-specific environment variables
if (!process.env.LANCE_LOG) {
process.env.LANCE_LOG = 'error';
}
if (!process.env.LANCEDB_LOG) {
process.env.LANCEDB_LOG = 'error';
}
// Note: Node.js cannot directly redirect file descriptor 2 (stderr) that native modules use
// The Rust-based LanceDB writes directly to fd 2, bypassing Node.js's process.stderr
// The only reliable way to suppress these logs is at the shell level:
// bloom-local-rag command 2>/dev/null
// bloom-local-rag command 2> >(grep -v "[TRACE\|DEBUG" >&2)
import { Command } from 'commander';
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { config as dotenvConfig } from 'dotenv';
import { initCommand } from './commands/init.js';
import { queryCommand } from './commands/query.js';
import { reindexCommand } from './commands/reindex.js';
import { statusCommand } from './commands/status.js';
// Load environment variables from .env file
dotenvConfig();
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Read package.json for version
const packageJson = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
const program = new Command();
program
.name('bloom-local-rag')
.description(`RAG (Retrieval-Augmented Generation) system for local directories.
This tool enables semantic search across your local documents with AI-powered answers.
It creates a vector database from your files and uses LLMs to provide contextual answers.
Key features:
• Index multiple file types (Markdown, code, YAML, etc.)
• Semantic search using vector embeddings
• AI-generated answers based on your documents
• Supports both Gemini and OpenAI models
• No daemon process required
Quick start:
1. Set up API key: export GOOGLE_API_KEY=your-key
2. Initialize: npx @masuidrive/bloom-local-rag --init
3. Search: npx @masuidrive/bloom-local-rag "your question"`)
.version(packageJson.version)
.argument('[query]', 'search query (default mode)')
.option('-d, --dir <path>', 'target directory (default: current directory)', (value, previous) => value)
.option('--directory <path>', 'target directory (default: current directory)', (value, previous) => value)
.option('--init', 'initialize RAG system in directory')
.option('--reindex', 'update the vector index with file changes')
.option('--status', 'display information about indexed documents')
.option('-l, --limit <n>', 'number of results (query mode)', parseInt, 5)
.option('--no-context', 'skip LLM answer generation (query mode)')
.option('--json', 'output as JSON (query mode)')
.option('--temperature <value>', 'LLM temperature (query mode)', parseFloat)
.option('-v, --verbose', 'show detailed information')
.option('--force', 'force reindex all files (reindex mode)')
.option('-e, --extensions <exts...>', 'file extensions to index (init mode)', ['.md', '.mdx', '.txt', '.js', '.ts', '.jsx', '.tsx', '.yaml', '.yml'])
.option('--chunk-size <size>', 'text chunk size (init mode)', parseInt, 1000)
.option('--chunk-overlap <size>', 'chunk overlap size (init mode)', parseInt, 200)
.option('--embedding-provider <provider>', 'embedding provider (init mode)', 'gemini')
.option('--embedding-model <model>', 'embedding model (init mode)')
.option('--llm-provider <provider>', 'LLM provider (init mode)', 'gemini')
.option('--llm-model <model>', 'LLM model (init mode)')
.option('--exclude <patterns...>', 'additional exclude patterns (init mode)', [])
.action(async (query, options) => {
// Merge directory options
const mergedOptions = {
...options,
directory: options.directory || options.dir
};
// Determine which mode to run
if (options.init) {
await initCommand(mergedOptions);
}
else if (options.reindex) {
await reindexCommand(mergedOptions);
}
else if (options.status) {
await statusCommand(mergedOptions);
}
else if (query) {
// Default query mode
await queryCommand(query, mergedOptions);
}
else {
// No query provided and no mode specified
program.outputHelp();
}
});
// Parse command line arguments
program.parse(process.argv);
//# sourceMappingURL=cli.js.map