[build-system] requires = ["setuptools>=77.0", "packaging>=24.2"] build-backend = "setuptools.build_meta" [project] name = "sponsio" version = "0.2.0a21" description = "Runtime contract enforcement for LLM agent systems" readme = "README.md" requires-python = ">=3.10" license = "Apache-2.0" authors = [ {name = "Sponsio Contributors"}, ] keywords = [ "llm", "agents", "safety", "contracts", "ltl", "runtime-verification", "langgraph", "mcp", ] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", ] # pyyaml is a HARD dependency, not optional: the config loader # (sponsio/config.py), the CLI host/plugin install path, sponsiorc, # and plugin scan/append all `import yaml` on the core code path. # A base `pip install sponsio` (or `pipx install sponsio`) must ship # it or `sponsio` onboarding crashes with ModuleNotFoundError (#61). dependencies = ["click>=8.0", "rich>=13.0", "questionary>=2.0", "pyyaml>=6.0"] [project.scripts] sponsio = "sponsio.cli:main" [project.urls] Homepage = "https://github.com/SponsioLabs/Sponsio" Repository = "https://github.com/SponsioLabs/Sponsio" Issues = "https://github.com/SponsioLabs/Sponsio/issues" [project.optional-dependencies] langgraph = ["langgraph", "langchain-core"] # openai: OpenAI + any OpenAI-compatible --base-url; google-genai: Gemini # (``from google import genai``); anthropic: Claude path for scan --llm llm = ["openai>=1.0", "google-genai", "anthropic"] crewai = ["crewai"] agents = ["openai-agents"] agents-sdk = ["openai-agents"] claude-agent = ["claude-agent-sdk"] google-adk = ["google-adk"] vercel-ai = ["vercel-ai-sdk"] web = ["fastapi>=0.100", "uvicorn[standard]>=0.20", "python-multipart>=0.0.6"] # Redundant now that pyyaml is a core dependency; kept so existing # `pip install sponsio[config]` invocations keep resolving. config = ["pyyaml>=6.0"] pdf = ["pdfplumber>=0.10"] # Verifying signed rule files (daemon.yaml ``signing:``). signing = ["cryptography>=42"] calibration = ["scikit-learn>=1.3"] otel = [ "opentelemetry-api>=1.20", "opentelemetry-sdk>=1.20", "opentelemetry-exporter-otlp-proto-http>=1.20", ] all = [ "langgraph", "langchain-core", "openai>=1.0", "google-genai", "anthropic", "crewai", "openai-agents", "claude-agent-sdk", "google-adk", "vercel-ai-sdk", "fastapi>=0.100", "uvicorn[standard]>=0.20", "python-multipart>=0.0.6", "opentelemetry-api>=1.20", "opentelemetry-sdk>=1.20", "opentelemetry-exporter-otlp-proto-http>=1.20", "pyyaml>=6.0", "pdfplumber>=0.10", "scikit-learn>=1.3", "cryptography>=42", ] # Pinned for the lint job. Ruff's `format` rules change between minor # versions, so a floating install drifts between local and CI. dev = ["ruff==0.17.1"] [tool.setuptools.packages.find] include = ["sponsio*"] [tool.setuptools.package-data] sponsio = [ "py.typed", # Built-in contract packs resolvable via `include: [sponsio:]` # — see `sponsio.config._resolve_include_spec`. Layout is # ``contracts//.yaml`` (core / capability / incident). "contracts/*/*.yaml", # Plugin default per-plugin libraries — copied by `sponsio plugin init` # into ``~/.sponsio/plugins//sponsio.yaml``. These are full # agent configs (not pack templates with ``*`` placeholders) — see # ``sponsio.plugin``. Mirrored under ``plugins/sponsio-claude-code/libraries/`` # for source-checkout users; ``tests/test_plugin_defaults_sync.py`` # keeps the two trees identical. "plugin/defaults/*.yaml", # Pre-built sponsio-openclaw plugin — bundled so # ``sponsio host install openclaw`` can deploy the OpenClaw # extension without requiring node/npm/tsc on the user's # machine. Canonical source: ``plugins/sponsio-openclaw/`` in # the repo; ``scripts/sync_openclaw_artifact.py`` mirrors the # built artifact here, and ``tests/test_openclaw_artifact_sync.py`` # fails the build if the two trees drift. "plugin/openclaw_artifact/*.json", "plugin/openclaw_artifact/*.md", "plugin/openclaw_artifact/dist/*.js", "plugin/openclaw_artifact/dist/*.d.ts", # Contract-extraction prompt templates (one per target host). # ``sponsio plugin prompt `` reads these and prints them so # the host agent driving ``sponsio plugin scan --introspect`` can # reason over the tool inventory using its own LLM context — no # separate API call needed from the CLI. "plugin/prompts/*.md", # Workflow prompt templates (onboard / scan). ``sponsio prompt # `` prints these for the host agent driving the ``sponsio`` # skill; pair with ``sponsio onboard --emit-context`` or # ``sponsio scan --emit-context``. "prompts/*.md", # Agent Skills (Cursor / Claude Code / Codex). Bundled so # ``sponsio skill install`` can locate the canonical source after # a pip install — see `sponsio.cli::skill_install`. Keep the nested # ``skills//`` layout so multiple skills can ship side # by side without path collision. "skills/*/SKILL.md", "skills/*/*.md", ] # Ruff config. The lint job (and `ruff format`) runs against a pinned # ruff (see the `dev` extra above). Defaults drift between ruff # versions, so pin the knobs the CI relies on explicitly here rather # than inheriting whatever the installed ruff happens to default to. # This codifies *current* behaviour (88-col, default E/F lint set) so # the config commit is a no-op against the existing tree — widening the # rule set (e.g. enabling `I` import sorting) is a separate change. [tool.ruff] line-length = 88 target-version = "py310" [tool.ruff.lint] select = ["E4", "E7", "E9", "F"] [tool.pytest.ini_options] testpaths = ["tests"] markers = [ "direct_only: exercises the file-backed hook path; not routed through the daemon", ]