[project] name = "numen" version = "0.2.0" description = "Proactive work intelligence platform - tells every person where to put their energy today" requires-python = ">=3.12" license = "AGPL-3.0-only" license-files = ["LICENSE"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python :: 3.12", "Topic :: Office/Business", ] dependencies = [ "fastapi>=0.115.0", "uvicorn[standard]>=0.30.0", "sqlalchemy[asyncio]>=2.0.0", "asyncpg>=0.30.0", "pgvector>=0.3.0", "alembic>=1.14.0", "httpx>=0.27.0", "openai>=1.0.0", "pydantic>=2.9.0", "pydantic-settings>=2.5.0", "python-dotenv>=1.0.0", "itsdangerous>=2.1.0", "redis[hiredis]>=5.0.0", "falkordb>=1.2.0", "resend>=2.0.0", "authlib>=1.3.0", "langchain>=0.3.0", "langchain-openai>=0.3.0", "pyjwt[crypto]>=2.8.0", "cryptography>=42.0.0", "slowapi>=0.1.9", # SDK 2.x is a rewrite (FastMCP -> MCPServer) implementing the stateless # 2026-07-28 protocol revision. Pin below it until src/mcp/ is migrated, # so a fresh install cannot silently break the server. "mcp[cli]>=1.9.0,<2", "markdown-it-py>=3.0.0", "beautifulsoup4>=4.12.0", "pyyaml>=6.0.0", "aioboto3>=13.0.0", "weasyprint>=62.0", "langgraph>=0.2.0", "pdfplumber>=0.11.0", "posthog>=3.7.0", ] [project.scripts] numen-mcp = "src.mcp.cli:main" [build-system] requires = ["setuptools>=69.0", "wheel"] build-backend = "setuptools.build_meta" # Numen is a flat layout whose single package is `src`, not a src-layout whose # packages live inside it. Without this, setuptools auto-discovery sees the # `src/` directory, assumes src-layout, and installs `agent`, `api`, `config`, # `main`, `events`, `shared` ... as top-level modules. Two things break: nothing # can `import src.config`, so console scripts like `alembic` and `uvicorn` fail # outside the repo root; and generic names like `config` and `main` shadow other # packages in any environment Numen is installed into. [tool.setuptools.packages.find] include = ["src*"] namespaces = false [project.optional-dependencies] dev = [ "pytest>=8.0.0", "pytest-asyncio>=0.24.0", "pytest-httpx>=0.30.0", "ruff>=0.6.0", "mypy>=1.11.0", "aiosqlite>=0.20.0", "fakeredis>=2.0.0", "pre-commit>=4.0.0", ] [tool.ruff] line-length = 120 target-version = "py312" exclude = ["website", "waitlist"] [tool.ruff.lint] select = ["E", "F", "I", "N", "W"] [tool.ruff.lint.per-file-ignores] "waitlist/lambda_function.py" = ["E501"] [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"]