[build-system] requires = ["setuptools>=64.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "piSynapse" version = "2.0.0" description = "Personal AI assistant — offline-first, multi-lingual, tool-calling" requires-python = ">=3.10" dependencies = [ "fastapi>=0.100.0", "uvicorn>=0.22.0", "python-multipart>=0.0.6", "pydantic>=2.0", "aiosqlite>=0.19.0", "bcrypt>=4.0.0", "cryptography>=42.0.0", "httpx>=0.24.0", "python-dotenv>=1.0.0", "caldav>=1.3.0", "vobject>=0.9.6.1", "fastembed>=0.3.0", "numpy>=1.24.0", "faster-whisper>=1.0.0", "piper-tts>=1.2.0", "icalendar>=5.0.0", ] [project.optional-dependencies] dev = [ "pytest>=7.0", "pytest-asyncio>=0.23.0", "ruff>=0.4.0", "mypy>=1.8.0", ] [tool.setuptools] # Every top-level module the app imports (auth/credstore/retrieval/title/ # textnorm/messages/tool_verification were missing → `pip install .` built an # incomplete package that ImportError'd). Kept in sync by # tests/test_packaging.py. py-modules = ["main", "config", "db", "embedding", "mail", "calendar_ops", "nextcloud_notes", "nextcloud_tasks", "weather", "prompt", "utils", "install", "auth", "credstore", "retrieval", "textnorm", "messages", "title", "tool_verification", "corpus_feeder", "provision_owner", "reembed_all"] packages = ["llm", "routers", "tools"] [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] python_files = ["test_*.py"] filterwarnings = [ "ignore::DeprecationWarning", # Upstream-only, not actionable yet: Starlette 1.x migrates TestClient # from httpx to the new httpx2 package, and FastAPI 0.140 still imports # the httpx path — the warning fires at import. Our RUNTIME uses httpx # v1 (LLM/Nextcloud calls), so "install httpx2" does not apply; drop this # filter once FastAPI ships httpx2 support. (StarletteDeprecationWarning # subclasses UserWarning, so ignore::DeprecationWarning misses it.) "ignore:Using `httpx` with `starlette.testclient` is deprecated:UserWarning", ] [tool.mypy] python_version = "3.10" strict = true ignore_missing_imports = true disallow_untyped_defs = false disallow_any_unimported = false warn_return_any = false warn_unused_ignores = true exclude = ["venv/", "__pycache__/", "models/"] [tool.ruff] target-version = "py310" line-length = 120 [tool.ruff.lint] select = ["E", "F", "W", "I", "N", "D", "UP"] # E402: router imports intentionally at the bottom of main.py (middleware first) # E501: line length is enforced by `ruff format`; redundant here # D205: docstring style, project keeps compact one-line summaries ignore = ["E402", "E501", "D205", "D100", "D101", "D102", "D103", "D104", "D105", "D107", "D200", "D210", "D400", "D401", "D402", "D404", "D405", "D406", "D407", "D408", "D409", "D410", "D411", "D412", "D413", "D414", "D415", "D416", "D417"]