From d122252e161348853966507577cc67b0b285d201 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 5 Sep 2025 11:45:33 +0300 Subject: [PATCH 1/3] If a document is deleted but does not exist, say so --- src/haiku/rag/app.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/haiku/rag/app.py b/src/haiku/rag/app.py index c9083cbd..74d52d0a 100644 --- a/src/haiku/rag/app.py +++ b/src/haiku/rag/app.py @@ -50,8 +50,13 @@ class HaikuRAGApp: async def delete_document(self, doc_id: str): async with HaikuRAG(db_path=self.db_path) as self.client: - await self.client.delete_document(doc_id) - self.console.print(f"[b]Document {doc_id} deleted successfully.[/b]") + deleted = await self.client.delete_document(doc_id) + if deleted: + self.console.print(f"[b]Document {doc_id} deleted successfully.[/b]") + else: + self.console.print( + f"[yellow]Document with id {doc_id} not found.[/yellow]" + ) async def search(self, query: str, limit: int = 5): async with HaikuRAG(db_path=self.db_path) as self.client: From 572e3605fe9bae1a790207530d6218caebe089fa Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 5 Sep 2025 12:00:40 +0300 Subject: [PATCH 2/3] Autocompletion for ids & paths --- src/haiku/rag/cli.py | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/haiku/rag/cli.py b/src/haiku/rag/cli.py index 45dca2f6..e1b8f785 100644 --- a/src/haiku/rag/cli.py +++ b/src/haiku/rag/cli.py @@ -22,6 +22,65 @@ cli = typer.Typer( console = Console() +def complete_document_ids(ctx: typer.Context, incomplete: str): + """Autocomplete document IDs from the selected DB.""" + db_path = ctx.params.get("db") or (Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb") + + try: + from haiku.rag.client import HaikuRAG + + async def _list_ids(): + async with HaikuRAG(db_path) as client: + docs = await client.list_documents() + return [d.id for d in docs if d.id] + + ids = asyncio.run(_list_ids()) + except Exception: + return [] + + return [i for i in ids if i and i.startswith(incomplete)] + + +def complete_local_paths(ctx: typer.Context, incomplete: str) -> list[str]: + """Autocomplete local filesystem paths. + + Provides directory/file suggestions based on the current incomplete input. + Does not validate or restrict to specific extensions to keep it flexible + (URLs are still allowed to be typed manually). + """ + try: + text = incomplete or "" + + # Expand user home + from os.path import expanduser + + expanded = expanduser(text) + p = Path(expanded) + + # Choose directory to list and prefix to filter + if text == "" or text.endswith(("/", "\\")): + directory = p + prefix = "" + else: + directory = p.parent + prefix = p.name + + if not directory.exists(): + return [] + + suggestions: list[str] = [] + for entry in directory.iterdir(): + name = entry.name + if not prefix or name.startswith(prefix): + suggestion = str(directory / name) + if entry.is_dir(): + suggestion += "/" + suggestions.append(suggestion) + return suggestions + except Exception: + return [] + + async def check_version(): """Check if haiku.rag is up to date and show warning if not.""" up_to_date, current_version, latest_version = await is_up_to_date() @@ -87,6 +146,7 @@ def add_document_text( def add_document_src( source: str = typer.Argument( help="The file path or URL of the document to add", + autocompletion=complete_local_paths, ), db: Path = typer.Option( Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb", @@ -102,6 +162,7 @@ def add_document_src( def get_document( doc_id: str = typer.Argument( help="The ID of the document to get", + autocompletion=complete_document_ids, ), db: Path = typer.Option( Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb", @@ -117,6 +178,7 @@ def get_document( def delete_document( doc_id: str = typer.Argument( help="The ID of the document to delete", + autocompletion=complete_document_ids, ), db: Path = typer.Option( Config.DEFAULT_DATA_DIR / "haiku.rag.lancedb", From 13bbdc2ed661307da674cf77bb1ed8f4ee3905b9 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 5 Sep 2025 12:04:20 +0300 Subject: [PATCH 3/3] Document autocomplete, add rm alias to delete --- docs/cli.md | 24 ++++++++++++++++++++++-- src/haiku/rag/cli.py | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index 5b7d6bb6..65f5eb91 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -2,6 +2,23 @@ The `haiku-rag` CLI provides complete document management functionality. +## Shell Autocompletion + +Enable shell autocompletion for faster, error‑free usage. + +- Temporary (current shell only): + ```bash + eval "$(haiku-rag --show-completion)" + ``` +- Permanent installation: + ```bash + haiku-rag --install-completion + ``` + +What’s completed: +- `get` and `delete`/`rm`: Document IDs from the selected database (respects `--db`). +- `add-src`: Local filesystem paths (URLs can still be typed manually). + ## Document Management ### List Documents @@ -26,13 +43,16 @@ haiku-rag add-src https://example.com/article.html ### Get Document ```bash -haiku-rag get 1 +haiku-rag get +# or +haiku-rag get 3f4a... # document ID (autocomplete supported) ``` ### Delete Document ```bash -haiku-rag delete 1 +haiku-rag delete +haiku-rag rm # alias ``` ### Rebuild Database diff --git a/src/haiku/rag/cli.py b/src/haiku/rag/cli.py index e1b8f785..c9e8fde2 100644 --- a/src/haiku/rag/cli.py +++ b/src/haiku/rag/cli.py @@ -190,6 +190,10 @@ def delete_document( asyncio.run(app.delete_document(doc_id=doc_id)) +# Add alias `rm` for delete +cli.command("rm", help="Alias for delete: remove a document by its ID")(delete_document) + + @cli.command("search", help="Search for documents by a query") def search( query: str = typer.Argument(