[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "hermes-agent"
version = "0.13.0"
description = "The self-improving AI agent — creates skills from experience, improves them during use, and runs anywhere"
readme = "README.md"
requires-python = ">=3.11"
authors = [{ name = "Nous Research" }]
license = { text = "MIT" }
dependencies = [
  # Core — pinned to known-good ranges to limit supply chain attack surface
  "openai>=2.21.0,<3",
  "anthropic>=0.39.0,<1",
  "python-dotenv>=1.2.1,<2",
  "fire>=0.7.1,<1",
  "httpx[socks]>=0.28.1,<1",
  "rich>=14.3.3,<15",
  "tenacity>=9.1.4,<10",
  "pyyaml>=6.0.2,<7",
  "requests>=2.33.0,<3",  # CVE-2026-25645
  "jinja2>=3.1.5,<4",
  "pydantic>=2.12.5,<3",
  # Interactive CLI (prompt_toolkit is used directly by cli.py)
  "prompt_toolkit>=3.0.52,<4",
  # Tools
  "exa-py>=2.9.0,<3",
  "firecrawl-py>=4.16.0,<5",
  "parallel-web>=0.4.2,<1",
  "fal-client>=0.13.1,<1",
  # Cron scheduler (built-in feature — scheduled cron/interval jobs use croniter).
  "croniter>=6.0.0,<7",
  # Text-to-speech (Edge TTS is free, no API key needed)
  "edge-tts>=7.2.7,<8",
  # Skills Hub (GitHub App JWT auth — optional, only needed for bot identity)
  "PyJWT[crypto]>=2.12.0,<3",  # CVE-2026-32597
]

[project.optional-dependencies]
modal = ["modal>=1.0.0,<2"]
daytona = ["daytona>=0.148.0,<1"]
vercel = ["vercel>=0.5.7,<0.6.0"]
dev = ["debugpy>=1.8.0,<2", "pytest>=9.0.2,<10", "pytest-asyncio>=1.3.0,<2", "pytest-xdist>=3.0,<4", "mcp>=1.2.0,<2", "ty>=0.0.1a29,<0.0.22", "ruff"]
messaging = ["python-telegram-bot[webhooks]>=22.6,<23", "discord.py[voice]>=2.7.1,<3", "aiohttp>=3.13.3,<4", "slack-bolt>=1.18.0,<2", "slack-sdk>=3.27.0,<4", "qrcode>=7.0,<8"]
cron = []  # croniter is now a core dependency; this extra kept for back-compat
slack = ["slack-bolt>=1.18.0,<2", "slack-sdk>=3.27.0,<4"]
matrix = ["mautrix[encryption]>=0.20,<1", "Markdown>=3.6,<4", "aiosqlite>=0.20", "asyncpg>=0.29", "aiohttp-socks>=0.10,<1"]
cli = ["simple-term-menu>=1.0,<2"]
tts-premium = ["elevenlabs>=1.0,<2"]
voice = [
  # Local STT pulls in wheel-only transitive deps (ctranslate2, onnxruntime),
  # so keep it out of the base install for source-build packagers like Homebrew.
  "faster-whisper>=1.0.0,<2",
  "sounddevice>=0.4.6,<1",
  "numpy>=1.24.0,<3",
]
pty = [
  "ptyprocess>=0.7.0,<1; sys_platform != 'win32'",
  "pywinpty>=2.0.0,<3; sys_platform == 'win32'",
]
honcho = ["honcho-ai>=2.0.1,<3"]
mcp = ["mcp>=1.2.0,<2"]
homeassistant = ["aiohttp>=3.9.0,<4"]
sms = ["aiohttp>=3.9.0,<4"]
acp = ["agent-client-protocol>=0.9.0,<1.0"]
mistral = ["mistralai>=2.3.0,<3"]
bedrock = ["boto3>=1.35.0,<2"]
termux = [
  # Baseline Android / Termux path for reliable fresh installs.
  "python-telegram-bot[webhooks]>=22.6,<23",
  "hermes-agent[cron]",
  "hermes-agent[cli]",
  "hermes-agent[pty]",
  "hermes-agent[mcp]",
  "hermes-agent[honcho]",
  "hermes-agent[acp]",
]
termux-all = [
  # Best-effort "install all" profile for Termux: include broad extras that
  # are known to resolve on Android, while intentionally excluding extras that
  # currently hard-fail from missing/broken Android wheels/toolchains.
  #
  # Excluded for now:
  # - matrix (mautrix[encryption] -> python-olm build failures on Termux)
  # - voice  (faster-whisper chain requires ctranslate2/av builds not packaged)
  "hermes-agent[termux]",
  "hermes-agent[messaging]",
  "hermes-agent[slack]",
  "hermes-agent[tts-premium]",
  "hermes-agent[dingtalk]",
  "hermes-agent[feishu]",
  "hermes-agent[google]",
  "hermes-agent[mistral]",
  "hermes-agent[bedrock]",
  "hermes-agent[homeassistant]",
  "hermes-agent[sms]",
  "hermes-agent[web]",
]
dingtalk = ["dingtalk-stream>=0.20,<1", "alibabacloud-dingtalk>=2.0.0", "qrcode>=7.0,<8"]
feishu = ["lark-oapi>=1.5.3,<2", "qrcode>=7.0,<8"]
google = [
  # Required by the google-workspace skill (Gmail, Calendar, Drive, Contacts,
  # Sheets, Docs).  Declared here so packagers (Nix, Homebrew) ship them with
  # the [all] extra and users don't hit runtime `pip install` paths that fail
  # in environments without pip (e.g. Nix-managed Python).
  "google-api-python-client>=2.100,<3",
  "google-auth-oauthlib>=1.0,<2",
  "google-auth-httplib2>=0.2,<1",
]
# `hermes dashboard` (localhost SPA + API).  Not in core to keep the default install lean.
web = ["fastapi>=0.104.0,<1", "uvicorn[standard]>=0.24.0,<1"]
rl = [
  "atroposlib @ git+https://github.com/NousResearch/atropos.git@c20c85256e5a45ad31edf8b7276e9c5ee1995a30",
  "tinker @ git+https://github.com/thinking-machines-lab/tinker.git@30517b667f18a3dfb7ef33fb56cf686d5820ba2b",
  "fastapi>=0.104.0,<1",
  "uvicorn[standard]>=0.24.0,<1",
  "wandb>=0.15.0,<1",
]
yc-bench = ["yc-bench @ git+https://github.com/collinear-ai/yc-bench.git@bfb0c88062450f46341bd9a5298903fc2e952a5c ; python_version >= '3.12'"]
all = [
  "hermes-agent[modal]",
  "hermes-agent[daytona]",
  "hermes-agent[vercel]",
  "hermes-agent[messaging]",
  # matrix: python-olm (required by matrix-nio[e2e]) is upstream-broken on
  # modern macOS (archived libolm, C++ errors with Clang 21+).  On Linux the
  # [matrix] extra's own marker pulls in the [e2e] variant automatically.
  "hermes-agent[matrix]; sys_platform == 'linux'",
  "hermes-agent[cron]",
  "hermes-agent[cli]",
  "hermes-agent[dev]",
  "hermes-agent[tts-premium]",
  "hermes-agent[slack]",
  "hermes-agent[pty]",
  "hermes-agent[honcho]",
  "hermes-agent[mcp]",
  "hermes-agent[homeassistant]",
  "hermes-agent[sms]",
  "hermes-agent[acp]",
  "hermes-agent[voice]",
  "hermes-agent[dingtalk]",
  "hermes-agent[feishu]",
  "hermes-agent[google]",
  "hermes-agent[mistral]",
  "hermes-agent[bedrock]",
  "hermes-agent[web]",
]

[project.scripts]
hermes = "hermes_cli.main:main"
hermes-agent = "run_agent:main"
hermes-acp = "acp_adapter.entry:main"

[tool.setuptools]
py-modules = ["run_agent", "model_tools", "toolsets", "batch_runner", "trajectory_compressor", "toolset_distributions", "cli", "hermes_constants", "hermes_state", "hermes_time", "hermes_logging", "rl_cli", "utils"]

[tool.setuptools.package-data]
hermes_cli = ["web_dist/**/*"]
gateway = ["assets/**/*"]

[tool.setuptools.packages.find]
include = ["agent", "agent.*", "tools", "tools.*", "hermes_cli", "gateway", "gateway.*", "tui_gateway", "tui_gateway.*", "cron", "acp_adapter", "plugins", "plugins.*", "providers", "providers.*"]

[tool.pytest.ini_options]
testpaths = ["tests"]
markers = [
    "integration: marks tests requiring external services (API keys, Modal, etc.)",
]
addopts = "-m 'not integration' -n auto"

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

[tool.ty.rules]
unknown-argument = "warn"
redundant-cast = "ignore"

[tool.ty.src]
exclude = ["tinker-atropos"]

[tool.ruff]
exclude = ["tinker-atropos"]
select = [] # disable all lints for now, until we've wrangled typechecks a bit more :3

[tool.uv]
exclude-newer = "7 days"
