Parse non-strings

This commit is contained in:
Yiorgis Gozadinos 2025-09-23 16:42:40 +03:00
parent 45d0b47a02
commit 8f3055d37d
No known key found for this signature in database
3 changed files with 39 additions and 5 deletions

View file

@ -40,8 +40,9 @@ haiku-rag add-src https://example.com/article.html
# Optionally set a humanreadable title stored in the DB schema
haiku-rag add-src /mnt/data/doc1.pdf --title "Q3 Financial Report"
# Optionally attach metadata (repeat --meta)
haiku-rag add-src /mnt/data/doc1.pdf --meta source=manual --meta lang=en
# Optionally attach metadata (repeat --meta). Values use JSON parsing if possible:
# numbers, booleans, null, arrays/objects; otherwise kept as strings.
haiku-rag add-src /mnt/data/doc1.pdf --meta source=manual --meta page_count=12 --meta published=true
```
!!! note

View file

@ -1,7 +1,9 @@
import asyncio
import json
import warnings
from importlib.metadata import version
from pathlib import Path
from typing import Any
import typer
@ -137,12 +139,12 @@ def list_documents(
asyncio.run(app.list_documents())
def _parse_meta_options(meta: list[str] | None) -> dict[str, str]:
def _parse_meta_options(meta: list[str] | None) -> dict[str, Any]:
"""Parse repeated --meta KEY=VALUE options into a dictionary.
Raises a Typer error if any entry is malformed.
"""
result: dict[str, str] = {}
result: dict[str, Any] = {}
if not meta:
return result
for item in meta:
@ -151,7 +153,13 @@ def _parse_meta_options(meta: list[str] | None) -> dict[str, str]:
key, value = item.split("=", 1)
if not key:
raise typer.BadParameter("--meta key cannot be empty")
result[key] = value
# Best-effort JSON coercion: numbers, booleans, null, arrays/objects
try:
parsed = json.loads(value)
result[key] = parsed
except Exception:
# Leave as string if not valid JSON literal
result[key] = value
return result

View file

@ -112,6 +112,31 @@ def test_add_document_src_with_meta():
assert kwargs.get("metadata") == {"source": "manual", "lang": "en"}
def test_add_document_text_with_numeric_meta():
with patch("haiku.rag.app.HaikuRAGApp") as mock_app:
mock_app_instance = MagicMock()
mock_app_instance.add_document_from_text = AsyncMock()
mock_app.return_value = mock_app_instance
result = runner.invoke(
cli,
[
"add",
"some text",
"--meta",
"version=3",
"--meta",
"published=true",
],
)
assert result.exit_code == 0
mock_app_instance.add_document_from_text.assert_called_once()
_, kwargs = mock_app_instance.add_document_from_text.call_args
assert kwargs.get("text") == "some text"
assert kwargs.get("metadata") == {"version": 3, "published": True}
def test_get_document():
with patch("haiku.rag.app.HaikuRAGApp") as mock_app:
mock_app_instance = MagicMock()