[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "hindsight-api"
version = "0.4.14"
description = "Hindsight: Agent Memory That Works Like Human Memory"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
    "asyncpg>=0.29.0",
    "python-dotenv>=1.0.0",
    "openai>=1.0.0",
    "pydantic>=2.0.0",
    "rich>=13.0.0",
    "langchain-text-splitters>=0.3.0",
    "fastapi[standard]>=0.120.3",
    "uvicorn>=0.38.0",
    "wsproto>=1.0.0",
    "sqlalchemy>=2.0.44",
    "alembic>=1.17.1",
    "pgvector>=0.4.1",
    "greenlet>=3.2.4",
    "psycopg2-binary>=2.9.11",
    "tiktoken>=0.12.0",
    "httpx>=0.27.0",
    "PyJWT[crypto]>=2.8.0",
    "fastmcp>=2.14.0", # CVE-2025-66416
    "pg0-embedded>=0.11.0",
    "python-dateutil>=2.8.0",
    "opentelemetry-api>=1.20.0",
    "opentelemetry-sdk>=1.20.0",
    "opentelemetry-instrumentation-fastapi>=0.41b0",
    "opentelemetry-exporter-prometheus>=0.41b0",
    "opentelemetry-exporter-otlp-proto-http>=1.20.0",
    "opentelemetry-semantic-conventions>=0.41b0",
    "dateparser>=1.2.2",
    "google-genai>=1.0.0",
    "google-auth>=2.0.0",
    "anthropic>=0.40.0",
    "typer>=0.9.0",
    "cohere>=5.0.0",
    "flashrank>=0.2.0",
    "litellm>=1.0.0",
    "markitdown[pdf,docx,pptx,xlsx,xls]>=0.1.4",  # File to markdown conversion
    "obstore>=0.4.0",  # S3/GCS/Azure object storage client (Rust-backed)
    # Local ML models for embeddings/reranking - can be excluded in Docker with INCLUDE_LOCAL_MODELS=false
    "sentence-transformers>=3.3.0",
    "transformers>=4.53.0", # Security fixes for ReDoS vulnerabilities
    "torch>=2.6.0", # CVE fix for remote code execution
    "uvloop>=0.22.1",
    # Transitive dependency security fixes
    "pyasn1>=0.6.2", # DoS vulnerability fix
    "urllib3>=2.6.3", # Decompression-bomb safeguards bypass fix
    "langchain-core>=1.2.5", # Serialization injection vulnerability fix
    "filelock>=3.20.1", # TOCTOU race condition fix
    "authlib>=1.6.6", # Account takeover vulnerability fix
    "aiohttp>=3.13.3", # Multiple DoS vulnerabilities
    "claude-agent-sdk>=0.1.27",
]

[project.optional-dependencies]
test = [
    "pytest>=7.0.0",
    "pytest-asyncio>=0.21.0",
    "pytest-timeout>=2.4.0",
    "pytest-xdist>=3.0.0",
    "filelock>=3.20.1",  # TOCTOU race condition fix
    "testcontainers>=4.0.0",
]

[project.scripts]
hindsight-api = "hindsight_api.main:main"
hindsight-worker = "hindsight_api.worker.main:main"
hindsight-local-mcp = "hindsight_api.mcp_local:main"
hindsight-admin = "hindsight_api.admin.cli:main"

[tool.hatch.build.targets.wheel]
packages = ["hindsight_api"]

[tool.hatch.build.targets.wheel.sources]
"hindsight_api" = "hindsight_api"

[tool.hatch.build.targets.sdist]
include = [
    "hindsight_api/**/*",
]

[tool.hatch.build]
include = [
    "hindsight_api/**/*.py",
    "hindsight_api/alembic/**/*",
]

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
addopts = "--timeout 300 -n 8 --dist loadgroup --durations=10 -v"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
log_auto_indent = true
filterwarnings = [
    "ignore:The @wait_container_is_ready decorator is deprecated:DeprecationWarning",
    "ignore::RuntimeWarning:asyncio",
]

[dependency-groups]
dev = [
    "pytest>=9.0.0",
    "pytest-asyncio>=1.3.0",
    "pytest-timeout>=2.4.0",
    "pytest-xdist>=3.8.0",
    "python-dotenv>=1.2.1",
    "filelock>=3.20.1",  # TOCTOU race condition fix
    "ruff>=0.8.0",
    "ty>=0.0.1",
    "testcontainers>=4.0.0",
]

[tool.ruff]
line-length = 120
target-version = "py311"
exclude = [
    "tests/",
    "**/tests/",
]

[tool.ruff.lint]
select = [
    "E",      # pycodestyle errors
    "W",      # pycodestyle warnings
    "F",      # Pyflakes
    "I",      # isort
]
ignore = [
    "E501",   # line too long (handled by formatter)
    "E402",   # module import not at top of file
    "F401",   # unused import (too noisy during development)
    "F841",   # unused variable (too noisy during development)
    "F811",   # redefined while unused
    "F821",   # undefined name (forward references in type hints)
]

[tool.ruff.lint.isort]
known-third-party = ["alembic"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

[tool.uv]
# Allow uv to search all configured indexes for packages, not just the first one
# This prevents dependency resolution failures when using pytorch index + PyPI
index-strategy = "unsafe-best-match"

[tool.ty]
# Type checking configuration
# ty is an extremely fast Python type checker from Astral (same team as ruff/uv)

[tool.ty.environment]
python-version = "3.11"

[tool.ty.src]
exclude = [
    "tests/",
    "hindsight_api/alembic/",
]

[tool.ty.rules]
# Disable noisy rules while keeping important ones
invalid-argument-type = "ignore"    # False positives with **kwargs patterns
invalid-return-type = "ignore"      # Often intentional in async code
invalid-parameter-default = "ignore" # Optional params with None default
possibly-missing-attribute = "ignore" # Common with Optional types
invalid-raise = "ignore"            # False positives with exception tracking
call-non-callable = "ignore"        # False positives with Optional types
invalid-key = "ignore"              # Pydantic ConfigDict not understood
invalid-method-override = "ignore"  # Intentional signature differences
unresolved-reference = "ignore"     # Forward references not always resolved
