FactsDB/factsdb/cli.py

126 lines
4.1 KiB
Python

"""
CLI interface for FactsDB service
Provides command line interface for onboarding directories
"""
import os
import click
from typing import Optional
from .config import Config
from .database import DatabaseManager
from .file_processor import FileProcessor
from .ai_processor import AIProcessor
from .scheduler import FactExtractionScheduler, get_scheduler
from .ftp_server import FTPServerManager
@click.group()
def cli():
"""FactsDB - Service for extracting and storing facts from documents"""
pass
@cli.command()
@click.option('--directory', '-d', required=True, help='Directory to onboard')
@click.option('--table-name', '-t', required=True, help='Name of table to store facts')
@click.option('--prompt', '-p', help='Custom prompt for AI extraction')
@click.option('--model', '-m', default='gpt-oss', help='AI model to use (default: gpt-oss)')
@click.option('--db-type', '-db', default='sqlite', help='Database type (default: sqlite)')
def onboard(directory: str, table_name: str, prompt: Optional[str], model: str, db_type: str):
"""Onboard a directory for fact extraction"""
click.echo(f"Onboarding directory: {directory}")
click.echo(f"Table name: {table_name}")
click.echo(f"AI model: {model}")
# Validate directory exists
if not os.path.exists(directory):
click.echo(f"Error: Directory {directory} does not exist")
return
# Create configuration
config = Config()
# Setup components
db_manager = DatabaseManager(config.database)
file_processor = FileProcessor()
ai_processor = AIProcessor(config.ai_endpoint)
scheduler = get_scheduler(config)
# Add job to scheduler
scheduler.add_job(directory, table_name, prompt or "", model)
click.echo(f"Successfully onboarded directory {directory} for fact extraction")
click.echo(f"Job scheduled to run every 10 minutes")
@cli.command()
def status():
"""Show current status and scheduled jobs"""
config = Config()
scheduler = get_scheduler(config)
click.echo("FactsDB Service Status")
click.echo("=" * 30)
jobs = scheduler.get_jobs()
if jobs:
click.echo("Scheduled Jobs:")
for i, job in enumerate(jobs, 1):
click.echo(f" {i}. Directory: {job['directory_path']}")
click.echo(f" Table: {job['table_name']}")
click.echo(f" Model: {job['model']}")
click.echo(f" Interval: {job['interval_minutes']} minutes")
click.echo()
else:
click.echo("No scheduled jobs")
@cli.command()
@click.option('--host', '-h', default='0.0.0.0', help='FTP server host')
@click.option('--port', '-p', default=21, type=int, help='FTP server port')
def ftp(host: str, port: int):
"""Start FTP server"""
config = Config()
# Fix: Use the correct config structure - ftp_server instead of ftp
config.ftp_server.host = host
config.ftp_server.port = port
# Fix: Pass the correct config object to FTPServerManager
ftp_manager = FTPServerManager(config)
# Add current directory as allowed directory
current_dir = os.path.abspath('.')
ftp_manager.add_allowed_directory(current_dir)
try:
ftp_manager.start_server()
click.echo(f"FTP Server started on {host}:{port}")
click.echo("Press Ctrl+C to stop")
# Keep running
try:
while True:
import time
time.sleep(1)
except KeyboardInterrupt:
ftp_manager.stop_server()
click.echo("FTP Server stopped")
except Exception as e:
click.echo(f"Error starting FTP server: {str(e)}")
@cli.command()
def tables():
"""Show all available tables and record counts"""
config = Config()
db_manager = DatabaseManager(config.database)
tables = db_manager.get_all_tables()
if not tables:
click.echo("No tables found")
return
click.echo("Available Tables:")
click.echo("=" * 40)
for table in tables:
click.echo(f"{table['table_name']}: {table['count']} records")
if __name__ == '__main__':
cli()