Files
Alberto Schiabel 62e51e838f chore(deps): refresh safe dependencies and Effect v4 (#4538)
## Summary

Refreshes the safe TypeScript, Python, and GitHub Actions dependency
surface in one maintainer-owned change. Effect 4 rc.115, Vitest 5, the
vendored Effect source, CLI migrations, and agent guidance move
together, while known incompatible boundaries stay pinned. The Effect v4
config schemas preserve unknown fields across `config.json` and
`user_data.json` read-update-write cycles.

Fixes #4535

## Changes

- Keeps Cloudflare Workers fixtures on Vitest 4 until
`@cloudflare/vitest-pool-workers` supports Vitest 5.
- Keeps Mastra on the Workers-compatible versions and AG2 below 1.0
because AG2 1.x no longer ships the imported `autogen` module.
- Removes the unused package-level `pnpm` dependency instead of changing
the repository's pinned pnpm 11 toolchain.
- Migrates the Effect CLI APIs, Eve callback contract, provider peer
ranges, and repository skills required by the selected upgrades.
- Preserves unknown CLI settings when `config.json` and `user_data.json`
are read, updated, and written back.
- Uses immutable SHA pins for the refreshed Claude Code actions and adds
release metadata for the affected published TypeScript packages.

## Type of change

- [x] Bug fix
- [ ] New feature
- [x] Refactor/Chore
- [x] Documentation
- [ ] Breaking change

## How Has This Been Tested?

- `pnpm install --frozen-lockfile` with pnpm 11.8.0
- `pnpm typecheck`
- `pnpm build:packages`
- `pnpm --filter @composio/cli test` — 1,400 passed, 1 skipped,
including targeted persistence regressions for `config.json` and
`user_data.json`
- Package tests — 28 workspace tasks passed
- Example typechecks/tests and all Cloudflare dry-runs
- Provider compatibility, experimental/Eve, Mastra, CLI keyring, and
JSON-schema Effect checks
- Agent-skill validation, routing validation, Effect skill example
compilation, and peer-dependency checks
- All three Python `uv lock --check` runs
- `nox -s tst_autogen`, `nox -s snt`, and `nox -s chk type_inference`
- Production dependency audit completed with the repository's three
existing ignored advisories

Docker CLI E2E was not run locally because the Docker daemon is
unavailable. The exact root lint command also enters the vendored Effect
submodule, whose checkout does not install its `@effect/oxc/oxlint`
plugin; scoped lint over the changed non-vendor files passed.

## Screenshots (if applicable)

Not applicable.

## Checklist

- [x] I have read the Code of Conduct and this PR adheres to it
- [ ] I ran linters/tests locally and they passed
- [x] I updated documentation as needed
- [x] I added tests or explain why not applicable
- [x] I added a changeset if this change affects published packages

The dependency migrations are covered by the focused and workspace
suites. Two targeted regression tests verify that CLI updates preserve
unknown fields in `config.json` and `user_data.json`.

## Additional context

The Connect client sync retains its existing `Bash(curl *)` permission
while moving the removed `allowed_tools` input to `claude_args`. A
separate hardening change should move logo downloads outside the
model-controlled shell boundary.

---

[![Compound
Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
2026-09-21 15:23:42 +04:00

235 lines
7.6 KiB
Python

import nox
from nox.sessions import Session
nox.options.default_venv_backend = "uv"
# Modules for both ruff and mypy
modules_for_mypy = [
"composio/",
"providers/",
"tests/",
"scripts/",
]
# Modules for ruff only (includes examples)
modules_for_ruff = [
"composio/",
"providers/",
"tests/",
"examples/",
"scripts/",
]
# Type stubs and provider libraries installed solely so mypy can resolve
# imports across `providers/` and `tests/`. These can't live in the locked
# `dev` dependency group: the provider libraries (crewai, langchain,
# llama-index, ...) would drag conflicting transitive deps into the root
# resolution. Shared test/lint tooling (ruff, pytest, fastapi, semver,
# langchain-openai) is sourced from the `dev` group in pyproject.toml via
# `--group dev`, so every package is declared in exactly one place.
type_stubs = [
"types-requests==2.33.0.20260906",
"types-protobuf==7.35.1.20260906",
"types-jsonschema==4.26.0.20260518",
"anthropic==0.120.0",
# Keep this aligned with the CrewAI provider dependency metadata.
"crewai==1.15.7",
"langchain==1.3.14",
"langgraph==1.2.9",
"llama-index==0.14.23",
"openai-agents==0.18.3",
"google-cloud-aiplatform==1.162.0",
# Keep this inside the TypeSafe provider's `>=0.6.0,<0.7.0` range.
"typesafe-sdk==0.6.0",
]
mypy = "mypy==2.3.1"
ruff = [
"ruff",
"--config",
"config/ruff.toml",
]
@nox.session
def fmt(session: Session):
"""Format code"""
session.install("--group", "dev")
session.run("ruff", "check", "--select", "I", "--fix", *modules_for_ruff)
session.run("ruff", "format", *modules_for_ruff)
@nox.session
def chk(session: Session):
"""Check for linter and type issues"""
session.install(".", "--group", "dev", mypy, *type_stubs)
session.run(*ruff, "check", *modules_for_ruff)
for module in modules_for_mypy:
session.run("mypy", "--config-file", "config/mypy.ini", module)
@nox.session
def fix(session: Session):
"""Fix linter issues"""
session.install("--group", "dev")
session.run(*ruff, "check", "--fix", *modules_for_ruff)
@nox.session
def chk_examples(session: Session):
"""Type-check example scripts against the SDK surface.
Examples run one mypy invocation per file: duplicate basenames
(examples/tools.py, examples/tool_router/tools.py) collide as module
names inside a single run. Third-party agent frameworks stay
unresolved on purpose; the check targets composio API usage.
"""
from pathlib import Path
session.install(".", "--group", "dev", mypy, *type_stubs)
for path in sorted(Path("examples").rglob("*.py")):
session.run(
"mypy",
"--config-file",
"config/mypy.ini",
"--ignore-missing-imports",
# Examples wrap their bodies in unannotated main()s; without this
# mypy skips those bodies entirely and the gate checks almost nothing.
"--check-untyped-defs",
str(path),
)
@nox.session
def tst(session: Session):
"""Run the Python unit test suite."""
session.install(".", "--group", "dev")
session.install("./providers/crewai")
session.install("./providers/langchain")
session.install("./providers/langgraph")
test_paths = session.posargs or ["tests/"]
session.run("pytest", *test_paths, "-v", "--tb=short")
@nox.session
def tst_autogen(session: Session):
"""Run Autogen tests in its protobuf-compatible environment."""
session.install(".", "--group", "dev")
session.install("./providers/autogen")
session.run(
"pytest",
"tests/test_provider.py::TestAgenticSkipDefaultsParity::test_autogen_signature_honors_skip_defaults",
"tests/test_provider.py::TestAgenticSkipDefaultsParity::test_autogen_signature_preserves_default",
"-v",
"--tb=short",
)
@nox.session
def tst_typesafe(session: Session):
"""Run the TypeSafe provider tests, which `tst` skips without the provider."""
session.install(".", "--group", "dev")
session.install("./providers/typesafe", "typesafe-sdk==0.6.0")
session.run(
"python",
"-c",
"import composio, composio_typesafe; "
"print(composio.__file__); print(composio_typesafe.__file__)",
)
session.run("pytest", "tests/test_typesafe_provider.py", "-v", "--tb=short")
@nox.session
def snt(session: Session):
"""Run fast sanity tests for imports and SDK initialization."""
session.install(".", "--group", "dev")
test_paths = session.posargs or ["tests/test_imports.py", "tests/test_sdk.py"]
session.run("pytest", *test_paths, "-v", "--tb=short")
@nox.session
def type_inference(session: Session):
"""Type check provider return type inference tests.
This session verifies that mypy correctly infers provider-specific return
types from `Composio.tools.get()` when using @overload signatures.
Unlike the `chk` session, this installs all provider packages so mypy can
resolve the provider types and verify the type inference works correctly.
"""
# Install core SDK, shared dev tooling, and mypy
session.install(".", "--group", "dev", mypy, *type_stubs)
# Install all provider packages for type resolution
session.install(
"./providers/anthropic",
"./providers/autogen",
"./providers/claude_agent_sdk",
"./providers/crewai",
"./providers/gemini",
"./providers/google",
"./providers/google_adk",
"./providers/langchain",
"./providers/langgraph",
"./providers/llamaindex",
"./providers/openai",
"./providers/openai_agents",
"./providers/typesafe",
)
# Run mypy on type inference test files
# Note: explicitly listed files are checked even if they match the exclude pattern in `mypy.ini`
session.run(
"mypy",
"--config-file",
"config/mypy.ini",
"tests/test_type_inference.py",
"tests/test_type_inference_anthropic.py",
"tests/test_type_inference_autogen.py",
"tests/test_type_inference_claude_agent_sdk.py",
"tests/test_type_inference_crewai.py",
"tests/test_type_inference_gemini.py",
"tests/test_type_inference_google.py",
"tests/test_type_inference_google_adk.py",
"tests/test_type_inference_langchain.py",
"tests/test_type_inference_langgraph.py",
"tests/test_type_inference_llamaindex.py",
"tests/test_type_inference_openai_agents.py",
"tests/test_type_inference_typesafe.py",
)
# Modules scanned for dead code (source only, no tests/examples/scripts)
modules_for_vulture = [
"composio/",
"providers/",
]
@nox.session(name="dead_code")
def dead_code(session: Session):
"""Report likely-dead code (unused functions, classes, variables).
Report-only: vulture exits 1 when it finds candidates, but we do not fail
the session on that so it never blocks CI on false positives. Vet the
output by hand; suppress confirmed false positives by adding the symbol to
``config/vulture_allowlist.py``. Ruff already covers unused imports (F401)
and unused locals (F841) in the `chk` session; vulture adds cross-module
unused functions/classes that ruff cannot see.
"""
session.install("vulture>=2.14")
session.run(
"vulture",
*modules_for_vulture,
"config/vulture_allowlist.py",
"--min-confidence",
"80",
"--exclude",
"*/build/*,*/dist/*,*/.venv/*,*/.nox/*,*/__pycache__/*",
# vulture exit codes: 0 = clean, 3 = candidates found. Report-only, so
# neither should fail the session. (1/2 are real usage/parse errors.)
success_codes=[0, 3],
)