deer-flow/backend/pyproject.toml
Rei 9cb2bde557
test(ci): run bundled extension behavior suites outside the core shards (#8180)
Bundled examples keep their behavior tests in backend/tests/, so the core
backend workflow ran optional extension behavior on every pull request. Mark
those suites with pytest.mark.bundled_extension, exclude them from the core
shards and from the duration baseline, and run them in a dedicated workflow
through make test-bundled-extensions. Tests of host mechanisms stay in the
core shards even when an example package is the payload.

The marked suites import deerflow.agents, config, runtime, knowledge and
app.gateway, so the workflow triggers for backend/packages/**,
backend/app/gateway/** and the marked test modules; a backend test pins those
paths, the make target and both marker selections, and fails when a marked
module is missing from the path list. Host/extension compatibility checks — a
host API gate and authorization of contributed routes — live in
test_extension_host_contracts.py so they still fail core CI. The committed
duration baseline drops the 482 entries for the excluded suites.

Refs #8173

Co-authored-by: REI-330 <173389910+REI-330@users.noreply.github.com>
Co-authored-by: willem-bd <143703838+willem-bd@users.noreply.github.com>
Co-authored-by: Eilen6316 <136898293+Eilen6316@users.noreply.github.com>
2026-11-14 09:12:25 +08:00

121 lines
5.5 KiB
TOML

[project]
name = "deer-flow"
version = "2.3.0-dev"
description = "LangGraph-based AI agent system with sandbox execution capabilities"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"deerflow-harness",
# Direct dependency on purpose, even though deerflow-harness already pulls
# it in: app/gateway/app.py and app/gateway/services.py import the public
# contract package themselves (the extension principal resolver, and the
# provenance key set the state route strips). Those are the app layer's own
# imports of a package whose whole point is a stable public surface, so the
# app declares them rather than relying on the harness to keep supplying it.
"deerflow-extension-api",
"fastapi>=0.115.0",
"httpx>=0.28.0",
"websockets>=16.0,<17",
"python-multipart>=0.0.31",
"sse-starlette>=2.1.0",
# Direct dependency on purpose, even though FastAPI already pulls it in:
# app/gateway/request_path.py imports the private
# `starlette._utils.get_route_path` so the auth and CSRF predicates
# classify the exact string Starlette's router matches on. A private
# import is the safest option here because it fails loudly (ImportError at
# startup) instead of silently drifting from the dispatcher at a security
# boundary -- but it does mean a Starlette bump is a security-relevant
# change. Declaring and bounding it here makes that bump visible in the
# diff; tests/test_gateway_request_path.py pins the agreement itself.
"starlette>=1.3.1,<2",
"uvicorn[standard]>=0.34.0",
"lark-oapi>=1.4.0",
"slack-sdk>=3.33.0",
"python-telegram-bot>=21.0",
"langgraph-sdk>=0.1.51",
"markdown-to-mrkdwn>=0.3.1",
"wecom-aibot-python-sdk>=0.1.6",
"dingtalk-stream>=0.24.3",
"bcrypt>=4.0.0",
"pyjwt>=2.13.0",
"email-validator>=2.0.0",
"e2b-code-interpreter>=2.8.1",
]
[project.optional-dependencies]
postgres = ["deerflow-harness[postgres]"]
redis = ["deerflow-harness[redis]"]
discord = ["discord.py>=2.7.0"]
buzz = ["coincurve>=20.0.0"]
monocle = ["deerflow-harness[monocle]"]
ollama = ["deerflow-harness[ollama]"]
browser = ["deerflow-harness[browser]"]
memory-zh = ["deerflow-harness[memory-zh]"]
[dependency-groups]
# Managed extension packages are added here by `deerflow extensions install`.
# Keeping them separate from development tooling lets every startup mode sync
# the same locked runtime set without promoting those packages to core deps.
extensions = []
dev = [
# Direct SDK use in Claude provider serialization tests.
"anthropic>=0.97.0",
"blockbuster>=1.5.26,<1.6",
"hypothesis>=6.100,<7",
"jsonschema>=4.26.0",
"prompt-toolkit>=3.0.0",
"pytest>=9.0.3",
"pytest-asyncio>=1.3.0",
"pytest-split>=0.11.0",
# Optional POSIX workflow worker. Wheels: CPython 3.12 macOS/Linux x86_64;
# other Python/CPU combinations need a C compiler + Python headers (see extension README).
"quickjs==1.19.4; sys_platform != 'win32'",
"ruff>=0.14.11",
# Monocle tracer (also the deerflow-harness[monocle] extra); kept in the dev
# group so the tracing tests can import it without forcing it onto installs.
"monocle_apptrace>=0.8.8",
# redis is an optional runtime extra (deerflow-harness[redis]); pin it in the
# dev group so the stream-bridge tests can always import/exercise the redis
# bridge without forcing it onto production installs.
"redis>=5.0.0",
# TUI runtime dep (also declared as the deerflow-harness[tui] extra); kept in
# the dev group so the terminal workbench can be run and tested locally / in CI.
"textual>=0.80",
]
[tool.pytest.ini_options]
markers = [
"no_auto_user: disable the conftest autouse contextvar fixture for this test",
"allow_blocking_io: opt out of the strict Blockbuster gate in tests/blocking_io/",
"integration: tests that require an external service (e.g. Redis); skipped when unavailable",
"live: tests that call real external APIs and require explicit opt-in",
"bundled_extension: behavior tests owned by a bundled extension example; excluded from the core shards and run by the bundled extension CI job",
]
[tool.uv]
index-url = "https://pypi.org/simple"
default-groups = ["dev", "extensions"]
# langgraph-sdk 0.4.2 (pulled in by langgraph 1.2.9 for DeltaChannel) pins
# `websockets<16,>=14`, silently downgrading websockets 16.0 -> 15.0.1. The
# pin is not grounded in any API incompatibility: websockets 16's only
# breaking change is requiring Python >=3.10 (we require >=3.12), the sdk
# only imports `websockets.asyncio.client`/`websockets.exceptions` (both
# 16-compatible), and DeerFlow never uses the sdk's WebSocket transport
# (httpx/SSE only). DeerFlow does have one direct consumer of its own: the Buzz
# channel (`app/channels/buzz.py`) imports the top-level `websockets` package and
# calls `websockets.connect()`, which in 16.0 is the same asyncio client the sdk
# uses, re-exported at the package root -- so it is covered by the same
# compatibility argument. Pin the exact pre-upgrade 16.0 for that plus the IM
# channel integrations (dingtalk-stream, python-telegram-bot, etc.) that ran on
# it before. Remove once langgraph-sdk relaxes the pin upstream. Note: enabling
# the `openai[realtime]` or `slack-sdk[optional]` extras would conflict (they
# also cap websockets<16).
override-dependencies = ["websockets==16.0"]
[tool.uv.workspace]
members = ["packages/harness", "packages/extension-api"]
[tool.uv.sources]
deerflow-harness = { workspace = true }
deerflow-extension-api = { workspace = true }