[project]
name = "ziran"
dynamic = ["version"]
description = "AI Agent Security Testing — discovers dangerous tool chain compositions via knowledge graph analysis"
readme = "README.md"
requires-python = ">=3.11"
license = { text = "Apache-2.0" }
authors = [{ name = "TaoQ AI", email = "leone@taoq.ai" }]
keywords = ["ai", "security", "testing", "agents", "llm", "vulnerability"]
classifiers = [
    "Development Status :: 3 - Alpha",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: Apache Software License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Topic :: Security",
    "Topic :: Software Development :: Testing",
    "Typing :: Typed",
]

dependencies = [
    "pydantic>=2.0,<3",
    "networkx>=3.2,<4",
    "httpx>=0.27,<1",
    "click>=8.1,<9",
    "rich>=13.7,<14",
    "pyyaml>=6.0,<7",
    "python-dotenv>=1.0,<2",
    "mdutils>=1.6,<2",
]

[project.optional-dependencies]
langchain = [
    "langchain>=0.2,<1",
    "langchain-community>=0.2,<1",
    "langchain-openai>=0.1,<1",
]
crewai = [
    "crewai>=0.30,<1",
]
a2a = [
    "a2a-sdk>=0.3,<1",
]
bedrock = [
    "boto3>=1.28,<2",
]
agentcore = [
    "bedrock-agentcore>=1.0,<2",
    "boto3>=1.28,<2",
]
llm = [
    "litellm>=1.40,<2",
]
pentest = [
    "ziran[llm]",
    "langgraph>=0.2,<1",
    "langchain-core>=0.3,<1",
    "numpy>=1.26,<3",
]
browser = [
    "playwright>=1.40,<2",
]
promptfoo = []
otel = [
    "opentelemetry-api>=1.20,<2",
    "opentelemetry-sdk>=1.20,<2",
]
all = [
    "ziran[langchain,crewai,a2a,bedrock,agentcore,llm,pentest,browser,promptfoo,otel]",
]

[project.scripts]
ziran = "ziran.interfaces.cli.main:cli"

[project.urls]
Homepage = "https://github.com/taoq-ai/ziran"
Documentation = "https://taoq-ai.github.io/ziran/"
Repository = "https://github.com/taoq-ai/ziran"
Issues = "https://github.com/taoq-ai/ziran/issues"

[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[tool.hatch.version]
source = "vcs"

[tool.hatch.build.hooks.vcs]
version-file = "ziran/_version.py"

[dependency-groups]
dev = [
    { include-group = "lint" },
    { include-group = "test" },
]
lint = [
    "ruff>=0.4",
    "mypy>=1.10",
    "types-PyYAML>=6.0",
]
test = [
    "pytest>=8.0,<9",
    "pytest-asyncio>=0.23",
    "pytest-cov>=5.0",
]

[tool.uv]
default-groups = ["dev"]

[tool.ruff]
target-version = "py311"
line-length = 100
exclude = ["ziran/_version.py"]  # auto-generated by hatch-vcs

[tool.ruff.lint]
select = [
    "E",   # pycodestyle errors
    "W",   # pycodestyle warnings
    "F",   # pyflakes
    "I",   # isort
    "N",   # pep8-naming
    "UP",  # pyupgrade
    "B",   # flake8-bugbear
    "SIM", # flake8-simplify
    "TCH", # flake8-type-checking
    "RUF", # ruff-specific
]
ignore = ["E501"]

[tool.ruff.lint.per-file-ignores]
"examples/**/*.py" = ["E402"]  # imports after load_dotenv() is intentional
"ziran/_version.py" = ["RUF022", "UP035", "UP006", "UP007", "I001"]  # auto-generated by hatch-vcs

[tool.ruff.lint.isort]
known-first-party = ["ziran"]

[tool.mypy]
python_version = "3.11"
plugins = ["pydantic.mypy"]
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true

[[tool.mypy.overrides]]
module = [
    "langchain.*",
    "langchain_core.*",
    "langchain_openai.*",
    "crewai.*",
    "networkx.*",
    "plotly.*",
    "mdutils.*",
    "a2a.*",
    "a2a_sdk.*",
    "boto3.*",
    "botocore.*",
    "litellm.*",
    "bedrock_agentcore.*",
    "websockets.*",
    "langgraph.*",
    "numpy.*",
    "playwright.*",
    "opentelemetry.*",
]
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
markers = [
    "unit: Unit tests",
    "integration: Integration tests",
]
addopts = "--strict-markers -v"

[tool.coverage.run]
source = ["ziran"]

[tool.coverage.report]
fail_under = 80
show_missing = true
