from __future__ import annotations
from pathlib import Path
import typer
from rich import print as rprint
from rich.table import Table
from .config import get_settings
from .loaders import list_docs, read_doc
from .index import build_index, search as search_index
from .server import main as mcp_main
app = typer.Typer(help="Local data indexer/searcher (MVP). MCP adapter coming soon.")
@app.command()
def ls(path: str | None = None) -> None:
"""List supported documents under DATA_DIR (or provided path)."""
s = get_settings()
root = Path(path) if path else s.data_dir
docs = list_docs(root)
table = Table(title=f"Files under {root}")
table.add_column("No.", justify="right")
table.add_column("Path")
for i, p in enumerate(docs, start=1):
table.add_row(str(i), str(p))
rprint(table)
@app.command()
def cat(file: str) -> None:
"""Print file content (best effort) to stdout."""
p = Path(file)
text = read_doc(p)
rprint(text[:4000]) # avoid huge dumps
@app.command()
def index() -> None:
"""Build embeddings index from DATA_DIR."""
build_index()
@app.command()
def search(query: str, k: int = 0) -> None:
"""Search top-k chunks."""
s = get_settings()
kk = k or s.top_k
results = search_index(query, kk)
table = Table(title=f"Top {kk} results for: {query}")
table.add_column("Rank", justify="right")
table.add_column("Score", justify="right")
table.add_column("File")
table.add_column("Chunk", overflow="fold")
for i, (meta, score, chunk_text) in enumerate(results, start=1):
table.add_row(str(i), f"{score:0.3f}", meta.path, chunk_text[:300])
rprint(table)
@app.command()
def run() -> None:
"""Run the MCP server over stdio."""
mcp_main()
def main() -> None:
app()
if __name__ == "__main__":
main()