cli.py carried 40 pragmas over whole command bodies and app.py a class-level one over all 412 statements, while tests/test_cli.py already drove 29 commands through CliRunner. The pragmas hid lines the suite executed, so the 100% gate understated real coverage and gave new CLI code no scrutiny. Both are measured now. 38 CLI tests stub HaikuRAGApp and assert the parsed arguments reach the right method; 60 app tests stub the client and record the console, pinning what each command asks for and what it prints. The only pragma left in either file is cli() under __main__. The omit list is back to the two Textual TUIs. Three defects the coverage surfaced: haiku-rag settings masked only top-level secret-named fields, so nested ones printed in full — lancedb.api_key, providers.docling_serve.api_key, WebDAV source passwords. It uses redact_secrets, which walks the dump. chat guarded the wrong thing: haiku.rag.chat imports without Textual, and run_chat raises when it imports ChatApp, so the missing extra escaped as an ImportError. The guard is on the call. inspector raises at module import instead, so inspect keeps its guard on the import; each has a test that fails the way the real installation fails. search --limit/--search-type and history --limit default to None so the config resolves the default. Now pinned. CI passed --cov=haiku while pyproject declares source = ["haiku_rag_slim"]; pass --cov and let the config decide. build-docs.yml only ran on push to main, so a broken docs build merged and failed at deploy: build on pull requests, with configure-pages, upload-pages-artifact and deploy gated to push, and a per-ref concurrency group.
170 lines
4.4 KiB
TOML
170 lines
4.4 KiB
TOML
[project]
|
|
|
|
name = "haiku.rag"
|
|
description = "Local-first agentic RAG with citations - hybrid search, reranking and multimodal retrieval over your own documents, no database server required"
|
|
version = "0.75.0"
|
|
authors = [{ name = "Yiorgis Gozadinos", email = "ggozadinos@gmail.com" }]
|
|
license = { text = "MIT" }
|
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
requires-python = ">=3.12"
|
|
keywords = [
|
|
"RAG",
|
|
"agentic-rag",
|
|
"lancedb",
|
|
"vector-database",
|
|
"hybrid-search",
|
|
"reranking",
|
|
"multimodal-rag",
|
|
"embeddings",
|
|
"citations",
|
|
"document-ingestion",
|
|
"mcp",
|
|
"mcp-server",
|
|
"pydantic-ai",
|
|
"docling",
|
|
]
|
|
classifiers = [
|
|
"Development Status :: 4 - Beta",
|
|
"Environment :: Console",
|
|
"Intended Audience :: Developers",
|
|
"Operating System :: Microsoft :: Windows :: Windows 10",
|
|
"Operating System :: Microsoft :: Windows :: Windows 11",
|
|
"Operating System :: MacOS",
|
|
"Operating System :: POSIX :: Linux",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Typing :: Typed",
|
|
]
|
|
|
|
dependencies = [
|
|
"haiku.rag-slim[docling,voyageai,cohere,zeroentropy,tui,cross-encoder,jina]==0.75.0",
|
|
]
|
|
|
|
[project.urls]
|
|
Homepage = "https://ggozad.github.io/haiku.rag/"
|
|
Documentation = "https://ggozad.github.io/haiku.rag/"
|
|
Repository = "https://github.com/ggozad/haiku.rag"
|
|
Issues = "https://github.com/ggozad/haiku.rag/issues"
|
|
Changelog = "https://ggozad.github.io/haiku.rag/changelog/"
|
|
|
|
[project.scripts]
|
|
haiku-rag = "haiku.rag.cli:cli"
|
|
|
|
[project.optional-dependencies]
|
|
tui = ["textual>=8.2.4"]
|
|
s3 = ["haiku.rag-slim[s3]==0.75.0"]
|
|
cross-encoder = ["haiku.rag-slim[cross-encoder]==0.75.0"]
|
|
ingester = ["haiku.rag-slim[ingester]==0.75.0"]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.hatch.build]
|
|
exclude = [
|
|
"/docs",
|
|
"/examples",
|
|
"/tests",
|
|
"/docker",
|
|
"/.github",
|
|
"/haiku_rag_slim",
|
|
"/evaluations",
|
|
]
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
only-include = ["/README.md"]
|
|
|
|
[tool.uv.workspace]
|
|
members = ["haiku_rag_slim", "evaluations"]
|
|
|
|
[tool.uv.sources]
|
|
"haiku.rag-slim" = { workspace = true }
|
|
"haiku.rag-evals" = { workspace = true }
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"haiku.rag-evals",
|
|
"haiku.rag-slim[ingester]",
|
|
"zensical",
|
|
"pre-commit>=4.5.1",
|
|
"pydantic-ai-slim[anthropic]",
|
|
"pydantic-ai-slim[bedrock]",
|
|
"pydantic-ai-slim[google]",
|
|
"pydantic-ai-slim[groq]",
|
|
"ty>=0.0.28",
|
|
"pytest>=9.0.2",
|
|
"pytest-asyncio>=1.3.0",
|
|
"pytest-cov>=7.1.0",
|
|
"pytest-recording>=0.13.4",
|
|
"pytest-xdist>=3.8.0",
|
|
"ruff>=0.15.9",
|
|
]
|
|
|
|
[tool.ruff]
|
|
line-length = 88
|
|
src = ["haiku_rag_slim"]
|
|
# Enable Flake's "E" and "F" codes by default and "I" for sorting imports.
|
|
# Exclude a variety of commonly ignored directories.
|
|
|
|
[tool.ruff.lint]
|
|
select = [
|
|
"E",
|
|
"F",
|
|
"UP",
|
|
"I",
|
|
] # Enable Flake's "E" and "F" codes by default and "I" for sorting imports
|
|
ignore = ["E501"]
|
|
per-file-ignores = { "__init__.py" = ["F401", "F403"] }
|
|
# Allow unused variables when underscore-prefixed.
|
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
|
|
[tool.ruff.lint.isort]
|
|
known-first-party = ["haiku"]
|
|
|
|
[tool.ruff.format]
|
|
quote-style = "double"
|
|
indent-style = "space"
|
|
skip-magic-trailing-comma = false
|
|
line-ending = "auto"
|
|
|
|
[tool.ty.src]
|
|
exclude = ["examples/**"]
|
|
|
|
[tool.ty.environment]
|
|
python-version = "3.12"
|
|
python = ".venv"
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_default_fixture_loop_scope = "session"
|
|
asyncio_mode = "auto"
|
|
addopts = "-n auto"
|
|
testpaths = ["tests"]
|
|
norecursedirs = ["examples", "docs", "evaluations", ".git", ".venv"]
|
|
markers = [
|
|
"integration: marks tests as integration tests (require external services)",
|
|
]
|
|
|
|
# pyproject.toml
|
|
filterwarnings = ["error", "ignore::UserWarning", "ignore::DeprecationWarning"]
|
|
|
|
[tool.coverage.run]
|
|
source = ["haiku_rag_slim"]
|
|
# aiosqlite runs sqlite (and the queue's PRAGMA connect listener) off the main
|
|
# flow via a greenlet + worker thread; track both so that code isn't reported
|
|
# as uncovered.
|
|
concurrency = ["greenlet", "thread"]
|
|
# Textual TUIs only: driving a terminal UI is not what this gate is for.
|
|
# Everything else, the CLI application layer included, is measured.
|
|
omit = [
|
|
"haiku_rag_slim/haiku/rag/chat/*",
|
|
"haiku_rag_slim/haiku/rag/inspector/*",
|
|
]
|
|
|
|
[tool.coverage.report]
|
|
show_missing = true
|
|
fail_under = 100
|
|
exclude_also = [
|
|
"if TYPE_CHECKING:",
|
|
"@abstractmethod",
|
|
"raise NotImplementedError",
|
|
]
|