cai/pyproject.toml

288 lines
7.3 KiB
TOML

[project]
name = "cai-framework"
version = "1.1.5"
description = "Cybersecurity AI Framework"
readme = "README.md"
requires-python = ">=3.10"
license = {text = "Dual-licensed MIT and Proprietary"}
authors = [{ name = "Alias Robotics", email = "research@aliasrobotics.com" }]
dependencies = [
# --- Core (always needed) ---
"openai>=1.75.0",
"httpx>=0.27", # Direct HTTP for alias models [N]
"pydantic>=2.10, <3",
"typing-extensions>=4.12.2, <5",
"rich",
"prompt_toolkit>=3.0.39",
"questionary>=2.0.1",
"python-dotenv>=0.19.0",
"pytz>=2024.1", # DataRecorder timestamps (run_to_jsonl); not always transitive
"PyYAML",
"wasabi>=1.1.3",
"tiktoken>=0.5", # Token counting
"mako>=1.3.8", # Prompt templates
"griffe>=1.5.6, <2", # Function schema generation
# --- LLM routing (still needed for non-alias models + proxy) ---
"litellm[proxy]>=1.80.5",
# --- TUI ---
"textual>=0.86.0",
# --- Networking & Tools ---
"requests>=2.0, <3",
"paramiko>=3.5.1", # SSH
"docker", # Container management
"cryptography>=42, <44",
# --- Web fetch tool (fetch_url) ---
"trafilatura>=2.0", # HTML -> Markdown main-content extraction
"curl-cffi>=0.7", # Anti-bot fallback (Chrome TLS fingerprint)
"pypdf>=4.0", # PDF text extraction (BSD-licensed successor of PyPDF2)
# --- API server ---
"uvicorn<=1",
"fastapi>=0.115.5, <1",
# --- Misc (used in specific modules) ---
"mcp", # Model Context Protocol
"nest_asyncio", # Async compat in sync contexts
]
classifiers = [
"Typing :: Typed",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules",
"License :: OSI Approved :: MIT License",
]
[project.urls]
Homepage = "https://github.com/aliasrobotics/cai"
Repository = "https://github.com/aliasrobotics/cai"
Documentation = "https://aliasrobotics.github.io/cai/"
Issues = "https://github.com/aliasrobotics/cai/issues"
Research = "https://cybersecurityrobotics.com/research/cai-bug-bounty-cybersecurity-ai/"
[project.optional-dependencies]
voice = ["numpy>=2.2.0", "websockets>=15.0"]
viz = ["graphviz>=0.17", "matplotlib>=3.0,<4", "networkx", "folium>=0.15.0,<1"]
data = ["numpy>=1.21,<3", "pandas>=1.3,<3", "scipy"]
# CTR graph canvas in the TUI needs networkx; full CTR solver needs numpy/scipy (see data/viz).
tui = ["networkx", "numpy>=1.21,<3", "scipy"]
docs = ["mkdocs>=1.6.0", "mkdocs-material>=9.6.0"]
mail = ["dnspython"]
pdf = ["PyPDF2"]
web = ["flask"]
telemetry = ["openinference-instrumentation-openai>=0.1.22"]
test = [
"pytest",
"pytest-asyncio",
"pytest-mock>=3.14.0",
"pytest-timeout",
"inline-snapshot>=0.20.7",
"graphviz>=0.17",
]
all = [
"cai-framework[viz,data,tui,docs,mail,pdf,web,telemetry,test]",
]
[dependency-groups]
dev = [
"mypy",
"ruff==0.9.2",
"pytest",
"pytest-asyncio",
"pytest-mock>=3.14.0",
"rich",
"mkdocs>=1.6.0",
"mkdocs-material>=9.6.0",
"mkdocstrings[python]>=0.28.0",
"coverage>=7.6.12",
"playwright==1.50.0",
"inline-snapshot>=0.20.7",
"pynput",
"types-pynput",
"sounddevice",
"textual",
"websockets",
"litellm>=1.63.7",
"prisma",
"graphviz",
"nest_asyncio"
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build]
exclude = [
".trunk/",
".git/",
".vscode/",
".devcontainer/",
".mypy_cache/",
".pytest_cache/",
".ruff_cache/",
"venv/",
".venv/",
"dist/",
"build/",
"*.egg-info/",
"workspaces/",
"benchmarks/",
"src/cai/caibench/",
"logs/",
"site/",
".cai/",
"nohup.out",
"ci/",
"tools/cut_the_rope/",
"private/",
"data/",
"tools/license_check.py",
"tools/create_root_user.sh",
"media/",
"docs/media/",
"docs"
]
[tool.hatch.build.targets.wheel]
packages = ["src/cai", "tools"]
exclude = [
".trunk/",
".git/",
".vscode/",
".devcontainer/",
".mypy_cache/",
".pytest_cache/",
".ruff_cache/",
"venv/",
".venv/",
"dist/",
"build/",
"*.egg-info/",
"workspaces/",
"benchmarks/",
"logs/",
"site/",
".cai/",
"nohup.out",
"ci/",
"tools/cut_the_rope/",
"private/",
"data/",
"tools/license_check.py",
"tools/create_root_user.sh",
"media/",
"docs/media/",
"docs"
]
# Explicitly include pricing data files
artifacts = [
"src/cai/pricings/*.json"
]
[tool.hatch.build.targets.wheel.sources]
"src" = ""
# Note: tools/cut_the_rope is excluded in the exclude list above
"tools" = "tools"
[tool.hatch.build.targets.sdist]
exclude = [
".trunk/",
".git/",
".vscode/",
".devcontainer/",
".mypy_cache/",
".pytest_cache/",
".ruff_cache/",
"venv/",
".venv/",
"dist/",
"build/",
"*.egg-info/",
"workspaces/",
"benchmarks/",
"logs/",
"site/",
".cai/",
"nohup.out",
"ci/",
"tools/cut_the_rope/",
"private/",
"data/",
"tools/license_check.py",
"tools/create_root_user.sh",
"media/",
"docs/media/",
"docs"
]
[tool.ruff]
line-length = 100
target-version = "py39"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]
isort = { combine-as-imports = true, known-first-party = ["agents"] }
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.per-file-ignores]
"examples/**/*.py" = ["E501"]
[tool.mypy]
strict = true
disallow_incomplete_defs = false
disallow_untyped_defs = false
disallow_untyped_calls = false
[[tool.mypy.overrides]]
module = "sounddevice.*"
ignore_missing_imports = true
[tool.coverage.run]
source = ["tests", "src/cai/sdk/agents"]
[tool.coverage.report]
show_missing = true
sort = "-Cover"
exclude_also = [
# This is only executed while typechecking
"if TYPE_CHECKING:",
"@abc.abstractmethod",
"raise NotImplementedError",
"logger.debug",
]
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
filterwarnings = [
# This is a warning that is expected to happen: we have an async filter that raises an exception
"ignore:coroutine 'test_async_input_filter_fails.<locals>.invalid_input_filter' was never awaited:RuntimeWarning",
]
markers = [
"allow_call_model_methods: mark test as allowing calls to real model implementations",
"slow: heavier imports (e.g. full agent graph); exclude with pytest -m \"not slow\" in fast slices",
]
[tool.inline-snapshot]
format-command = "ruff format --stdin-filename {filename}"
[project.scripts]
cai = "cai.cli:main"
cai-replay = "tools.replay:main"
cai-asciinema = "tools.asciinema:main"
cai-gif = "tools.gif:main"
cai-bench = "cai.caibench.cli:main"
cai-ctr = "tools.ctr_experiment:main"