diff --git a/.github/workflows/local-backends.yml b/.github/workflows/local-backends.yml index 12cd6f15..597b4aec 100644 --- a/.github/workflows/local-backends.yml +++ b/.github/workflows/local-backends.yml @@ -48,6 +48,8 @@ jobs: uv run --no-project --with tomlkit python scripts/bump_version.py uv lock --check git checkout -- pyproject.toml packages/agentenv-protocol/pyproject.toml uv.lock + - name: Lint + run: .venv/bin/ruff check - name: Unit tier run: .venv/bin/python -m pytest tst/unit packages/agentenv-protocol/tests -n auto -q --timeout=300 --junitxml=junit-unit.xml diff --git a/AGENTS.md b/AGENTS.md index 2ec621ba..7dfd01d2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,6 +39,7 @@ or one of them only where it is used. | Command | What it does | |---|---| +| `make lint` | `ruff check` over the repository, with the rules in `pyproject.toml` (pyflakes) | | `make unit-test` | `tst/unit` and `packages/agentenv-protocol/tests`, in parallel, no network | | `make int-test-fast` | `tst/integration` minus `int_test_slow`, in parallel; needs Docker and a local OCI registry (`docker run -d -p 5000:5000 public.ecr.aws/docker/library/registry:2`) | | `make int-test-slow` | the `int_test_slow` tests, serially (they build the same Docker tags from module fixtures and race under xdist) | @@ -195,7 +196,8 @@ The required checks on pull requests and `main` are `unit`, `integration-local`, `integration-local-slow`, `installer`, `plugin-api` and `clean-install`. `.github/workflows/local-backends.yml` runs the first four, all installed from `uv.lock` (public PyPI only) with no secrets and no external services (a `registry:2` service container for the integration jobs). The `unit` job also fails if `uv.lock` resolves anything from a registry other than PyPI or if -`agentenv-framework-protocol` is not the editable workspace member. The integration jobs run +`agentenv-framework-protocol` is not the editable workspace member, or if `ruff check` reports a +problem. The integration jobs run `.github/scripts/check_skip_policy.py` over the JUnit report: only `agentenv-capability-missing` skips for the allowed capabilities pass, and the fast job allows no skips under `tst/integration/store/`. The `installer` job runs `tst/installer` when a pull request or push diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 27cb6dd0..e7ea0d09 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,6 +37,7 @@ reinstalling. | Command | What it runs | Needs | |---|---|---| +| `make lint` | `ruff check`, with the rules in `pyproject.toml`; the `unit` job runs it too | nothing external | | `make unit-test` | unit suite for `agentenv-framework` and `agentenv-framework-protocol` | nothing external | | `make int-test-fast` | integration tests against the local backends | Docker | | `make int-test-slow` | tests that build images or deploy sandboxes, minutes each | Docker, and a sandbox backend for some | diff --git a/Makefile b/Makefile index 024ad91d..17cf0ef0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help install unit-test int-test int-test-fast int-test-slow installer-test clean-install-test test clean +.PHONY: help install lint unit-test int-test int-test-fast int-test-slow installer-test clean-install-test test clean VENV := .venv VENV_BIN := $(abspath $(VENV))/bin @@ -22,6 +22,9 @@ install: ## Create .venv and install the package with dev dependencies $(PIP) install -e ./packages/agentenv-protocol $(PIP) install -e ".[dev]" +lint: ## Lint with ruff, the check the unit job runs + $(VENV_BIN)/ruff check + unit-test: ## Run the unit test suite in parallel (no external services) $(PYTHON) -m pytest tst/unit/ packages/agentenv-protocol/tests/ -n auto diff --git a/pyproject.toml b/pyproject.toml index 41a1d57f..450a7f3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,6 +92,7 @@ dev = [ "pytest-socket>=0.7.0", "pytest-timeout>=2.3.0", "pytest-xdist>=3.0.0", + "ruff==0.16.10", # the lint gate; exact, since what it reports changes between releases ] [project.scripts] @@ -138,3 +139,6 @@ markers = [ log_cli = true log_cli_level = "INFO" log_cli_format = "%(asctime)s %(levelname)s %(name)s: %(message)s" + +[tool.ruff.lint] +select = ["F"] diff --git a/src/agent_env/a2a_agent/store.py b/src/agent_env/a2a_agent/store.py index 11fb983f..404f4cc3 100644 --- a/src/agent_env/a2a_agent/store.py +++ b/src/agent_env/a2a_agent/store.py @@ -21,7 +21,7 @@ from agent_env.store.query import QueryBuilder, to_document_query if TYPE_CHECKING: - from agent_env.a2a_agent.a2a_agent import A2AAgent + from agent_env.a2a_agent.a2a_agent import A2AAgent, DeployedA2AAgent logger = logging.getLogger(__name__) diff --git a/src/agent_env/a2a_agent/validator.py b/src/agent_env/a2a_agent/validator.py index 457184ed..b814eae9 100644 --- a/src/agent_env/a2a_agent/validator.py +++ b/src/agent_env/a2a_agent/validator.py @@ -163,7 +163,6 @@ async def validate( from agent_env.task_step.task_steps.peer_agents import AgentPeers, PeerAgentsTaskStep from agent_env.task_step.task_steps.snapshot_agent_state import SnapshotAgentStateTaskStep from agent_env.task_step.task_step import TaskStep, TaskStepDependency - from agent_env.a2a_agent.a2a_agent import A2AAgent task_id = derive_id(agent.id, f"validate-a2a-v{agent.version}") diff --git a/src/agent_env/artifact/artifacts/docker_image.py b/src/agent_env/artifact/artifacts/docker_image.py index e95b6263..abf99242 100644 --- a/src/agent_env/artifact/artifacts/docker_image.py +++ b/src/agent_env/artifact/artifacts/docker_image.py @@ -5,7 +5,6 @@ import asyncio import gzip import logging -import os import posixpath import re import shlex @@ -13,7 +12,6 @@ import tempfile import uuid from dataclasses import dataclass -from importlib.metadata import version as pkg_version from pathlib import Path from typing import Any, Callable, ClassVar, Literal from urllib.parse import urlparse diff --git a/src/agent_env/bundle/__init__.py b/src/agent_env/bundle/__init__.py index 5d5c6452..49ed558c 100644 --- a/src/agent_env/bundle/__init__.py +++ b/src/agent_env/bundle/__init__.py @@ -2,3 +2,20 @@ from .parse import Bundle, BundleEntry, BundleError, BundleKind, is_ignored, parse_bundle from .run import BundleRun, DryRun, EvalRun, Outcome, RunInterrupted, TaskRun, dry_run_bundle, run_bundle + +__all__ = [ + "Bundle", + "BundleEntry", + "BundleError", + "BundleKind", + "BundleRun", + "DryRun", + "EvalRun", + "Outcome", + "RunInterrupted", + "TaskRun", + "dry_run_bundle", + "is_ignored", + "parse_bundle", + "run_bundle", +] diff --git a/src/agent_env/cli/a2a_agent/put.py b/src/agent_env/cli/a2a_agent/put.py index 9dac8a33..d1a15678 100644 --- a/src/agent_env/cli/a2a_agent/put.py +++ b/src/agent_env/cli/a2a_agent/put.py @@ -63,10 +63,10 @@ def put(agent_id: str, dockerfile: str | None, context_path: str | None, image_r context = Path(context_path) if context_path else dockerfile_path.parent image_tag = image_repository(image_id) - click.echo(f"Building Docker image...") + click.echo("Building Docker image...") build_image(dockerfile_path, context, image_tag, platform=build_platform) - click.echo(f"Creating DockerImageArtifact...") + click.echo("Creating DockerImageArtifact...") artifact = DockerImageArtifact.put( id=image_id, description=f"A2A agent image for {agent_id}", @@ -83,7 +83,7 @@ def put(agent_id: str, dockerfile: str | None, context_path: str | None, image_r if default_model is not None: metadata["default_model"] = default_model - click.echo(f"Registering A2A agent...") + click.echo("Registering A2A agent...") agent = A2AAgent.put( id=agent_id, docker_image_artifact=artifact, diff --git a/src/agent_env/cli/env/deploy.py b/src/agent_env/cli/env/deploy.py index 7d84f754..65fc9274 100644 --- a/src/agent_env/cli/env/deploy.py +++ b/src/agent_env/cli/env/deploy.py @@ -91,7 +91,7 @@ def deploy(env_id: str, env_version: int | None, ttl_seconds: int, gateway_mode: click.echo(f"Error: {e}", err=True) raise SystemExit(1) - click.echo(f"Deployed!") + click.echo("Deployed!") if deployed_env.instance_id: click.echo("Instance ID: " + click.style(deployed_env.instance_id, fg="green")) click.echo("Env MCP Url: " + click.style(deployed_env.mcp_url, fg="blue")) diff --git a/src/agent_env/cli/env/mcp_server.py b/src/agent_env/cli/env/mcp_server.py index e4c8ab94..82696df4 100644 --- a/src/agent_env/cli/env/mcp_server.py +++ b/src/agent_env/cli/env/mcp_server.py @@ -209,10 +209,10 @@ def _on_progress(step: str, message: str, percent: int) -> None: sys.exit(1) click.echo(f"Derived environment_name={environment_name!r} from the environment card.") image_tag = image_repository(image_id) - click.echo(f"Building MCP server Docker image...") + click.echo("Building MCP server Docker image...") build_image(dockerfile_path, context, image_tag, platform=build_platform) - click.echo(f"Creating DockerImageArtifact...") + click.echo("Creating DockerImageArtifact...") artifact = DockerImageArtifact.put( id=image_id, description="Created from agent-env CLI", @@ -227,7 +227,7 @@ def _on_progress(step: str, message: str, percent: int) -> None: report_dirs = [str(context), str(dockerfile_path.parent)] metadata.update(user_metadata) - click.echo(f"Creating MCPServerEnv...") + click.echo("Creating MCPServerEnv...") env = MCPServerEnv.put( id=env_id, docker_image_artifact=artifact, diff --git a/src/agent_env/cli/env/multi.py b/src/agent_env/cli/env/multi.py index 848c035f..282e63b7 100644 --- a/src/agent_env/cli/env/multi.py +++ b/src/agent_env/cli/env/multi.py @@ -74,7 +74,7 @@ def put(env_id: str, mcp_servers: tuple[str, ...], websites: tuple[str, ...], me if refusal: click.echo(f"Error: {refusal}", err=True) raise SystemExit(1) - click.echo(f"Creating MultiEnv...") + click.echo("Creating MultiEnv...") multi_env = MultiEnv.put(id=env_id, mcp_server_envs=mcp_server_envs, website_envs=website_envs, metadata=metadata if metadata else None, name=name, env_provider_type=env_provider_type) click.echo(f"Created MultiEnv: id={multi_env.id} version={multi_env.version} env_provider_type={multi_env.env_provider_type}") @@ -243,7 +243,6 @@ def validate_universe_compatibility(env_id: str, env_version: int | None, univer instance_id = asyncio.run(env.validate_universe_compatibility(universe_artifact_id=universe_artifact_id, on_progress=click.echo)) click.echo(f"Task instance: {instance_id}") - from agent_env.env.env_artifact_store import get_env_artifact_store from agent_env.env.env_artifact_store import EnvArtifactType, get_env_artifact_store results = get_env_artifact_store().get_by_env(env_id, env_version=env.version, type=EnvArtifactType.UNIVERSE_COMPATIBILITY) doc = next((r for r in results if r["artifact_id"] == universe_artifact_id), None) diff --git a/src/agent_env/cli/env/state/init.py b/src/agent_env/cli/env/state/init.py index 271452ad..5a67937b 100644 --- a/src/agent_env/cli/env/state/init.py +++ b/src/agent_env/cli/env/state/init.py @@ -5,12 +5,16 @@ """ import asyncio +from typing import TYPE_CHECKING import click from agent_env.env import Env, MultiEnv from agent_env.store.routing import run_scope +if TYPE_CHECKING: + from agent_env.providers.env_state import EnvStateInstance + # A durable store can't be shorter-lived than a normal run, so the floor is the default run TTL # (agent-env's current default, mirrored from cli/env/deploy.py). MIN_TTL_SECONDS = 10800 # 3 hours (= default run TTL) diff --git a/src/agent_env/cli/env/website.py b/src/agent_env/cli/env/website.py index dd2e6041..f10930fd 100644 --- a/src/agent_env/cli/env/website.py +++ b/src/agent_env/cli/env/website.py @@ -17,9 +17,7 @@ ) from agent_env.utils.card_naming import card_name_from_github, card_name_from_source from agent_env.utils.docker_build import DEFAULT_BUILD_PLATFORM, build_image -from agent_env.env import Env from agent_env.env.envs.website import WebsiteEnv -from agent_env.providers import get_env_sandbox_provider from agent_env.store.ids import derive_id, image_repository @@ -152,10 +150,10 @@ def _frontend_progress(step: str, message: str, percent: int) -> None: sys.exit(1) click.echo(f"Derived environment_name={environment_name!r} from the environment card.") - click.echo(f"Building website backend Docker image...") + click.echo("Building website backend Docker image...") build_image(backend_dockerfile_path, backend_ctx, backend_tag, platform=build_platform) - click.echo(f"Creating backend DockerImageArtifact...") + click.echo("Creating backend DockerImageArtifact...") backend_artifact = DockerImageArtifact.put( id=backend_id, description="Website backend image created from agent-env CLI", @@ -167,10 +165,10 @@ def _frontend_progress(step: str, message: str, percent: int) -> None: frontend_ctx = Path(frontend_docker_context) if frontend_docker_context else frontend_dockerfile_path.parent frontend_tag = image_repository(frontend_id) - click.echo(f"Building website frontend Docker image...") + click.echo("Building website frontend Docker image...") build_image(frontend_dockerfile_path, frontend_ctx, frontend_tag, platform=build_platform) - click.echo(f"Creating frontend DockerImageArtifact...") + click.echo("Creating frontend DockerImageArtifact...") frontend_artifact = DockerImageArtifact.put( id=frontend_id, description="Website frontend image created from agent-env CLI", @@ -181,7 +179,7 @@ def _frontend_progress(step: str, message: str, percent: int) -> None: metadata = detect_env_metadata(backend_dockerfile_path, backend_ctx) metadata.update(user_metadata) - click.echo(f"Creating WebsiteEnv...") + click.echo("Creating WebsiteEnv...") env = WebsiteEnv.put( id=env_id, backend_docker_image_artifact=backend_artifact, diff --git a/src/agent_env/cli/eval/run.py b/src/agent_env/cli/eval/run.py index 89353d9a..80f98cb0 100644 --- a/src/agent_env/cli/eval/run.py +++ b/src/agent_env/cli/eval/run.py @@ -98,7 +98,7 @@ def run(eval_id: str, eval_version: int | None, output_dir: str | None, k: int, tasks = [] for et in eval_obj.tasks: task = Task.get(et.task_id, version=et.task_version) - version_note = f" (resolved from latest)" if et.task_version is None else "" + version_note = " (resolved from latest)" if et.task_version is None else "" click.echo(f" Loaded task: {task.id} v{task.version} ({len(task.steps)} steps){version_note}") tasks.append(task) diff --git a/src/agent_env/config/runtime.py b/src/agent_env/config/runtime.py index 98958916..2e1e6c7c 100644 --- a/src/agent_env/config/runtime.py +++ b/src/agent_env/config/runtime.py @@ -35,8 +35,6 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Callable, Mapping, Optional -import yaml - from agent_env.config import loader as config_loader from agent_env.config import model as model_config from agent_env.config.errors import ConfigError, EmptySecretBundleError diff --git a/src/agent_env/env/envs/mcp_server.py b/src/agent_env/env/envs/mcp_server.py index e68223e5..5249a3c3 100644 --- a/src/agent_env/env/envs/mcp_server.py +++ b/src/agent_env/env/envs/mcp_server.py @@ -7,11 +7,11 @@ import os import uuid from importlib.metadata import version as pkg_version -from typing import TYPE_CHECKING, Callable, ClassVar, Optional +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional from agentenv_protocol import FilePart, client as protocol_v1 from agent_env.artifact import Artifact, DockerImageArtifact -from agent_env.artifact.artifacts.docker_image import GitHubBuildResult, ProgressCallback, refuse_local_github_build +from agent_env.artifact.artifacts.docker_image import ProgressCallback, refuse_local_github_build from agent_env.config import get_config from agent_env.entity_refs import EntityRef from agent_env.env.env import Env, gateway_url_of @@ -28,7 +28,7 @@ if TYPE_CHECKING: from agent_env.artifact import CliArtifact, EnvironmentArtifact, EnvironmentUniverseArtifact from agent_env.bundle.authoring import AuthoringContext - from agent_env.env.env import DeployedEnv + from agent_env.env.env import DeployedEnv, LoadFileArtifactUniverseResult from agent_env.providers.env_providers.env_provider import EnvironmentProvider logger = logging.getLogger(__name__) diff --git a/src/agent_env/env/envs/multi_env.py b/src/agent_env/env/envs/multi_env.py index 5fdaf27a..25720963 100644 --- a/src/agent_env/env/envs/multi_env.py +++ b/src/agent_env/env/envs/multi_env.py @@ -3,7 +3,7 @@ import logging import os -from typing import TYPE_CHECKING, Callable, ClassVar, Optional +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional logger = logging.getLogger(__name__) @@ -23,6 +23,7 @@ def _snapshot_after_load_default() -> bool: if TYPE_CHECKING: from agent_env.artifact import EnvironmentArtifact, EnvironmentUniverseArtifact from agent_env.bundle.authoring import AuthoringContext + from agent_env.env.env import DeployedEnv, LoadEnvironmentUniverseArtifactResult, LoadFileArtifactUniverseResult from agent_env.providers.env_state import DatabaseStateProvider from agent_env.entity_refs import EntityRef diff --git a/src/agent_env/env/envs/website.py b/src/agent_env/env/envs/website.py index da969844..715b1715 100644 --- a/src/agent_env/env/envs/website.py +++ b/src/agent_env/env/envs/website.py @@ -7,11 +7,11 @@ import os import uuid from importlib.metadata import version as pkg_version -from typing import TYPE_CHECKING, Callable, ClassVar, Optional +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional from agentenv_protocol import FilePart, client as protocol_v1 from agent_env.artifact import Artifact, DockerImageArtifact, EnvironmentArtifact -from agent_env.artifact.artifacts.docker_image import GitHubBuildResult, ProgressCallback, refuse_local_github_build +from agent_env.artifact.artifacts.docker_image import ProgressCallback, refuse_local_github_build from agent_env.entity_refs import EntityRef from agent_env.env.env import Env, gateway_url_of from agent_env.store.ids import derive_id @@ -20,11 +20,11 @@ as_builtin, builtin_provider_for, close_deployed, close_replaced, deploy_refusal, deploy_through_provider, host_staging_refusal, load_by_signed_url, plugin_provider_like_a_builtin, provider_or_class, ) -from agent_env.env.gateway import AGENT_ENV_GATEWAY_MCP_PORT, GatewayMode +from agent_env.env.gateway import GatewayMode from agent_env.attribution import Attribution if TYPE_CHECKING: from agent_env.bundle.authoring import AuthoringContext - from agent_env.env.env import DeployedEnv + from agent_env.env.env import DeployedEnv, LoadFileArtifactUniverseResult from agent_env.providers.env_providers.env_provider import EnvironmentProvider logger = logging.getLogger(__name__) diff --git a/src/agent_env/env/gateway/gateway.py b/src/agent_env/env/gateway/gateway.py index 2e86d3a8..4a4a4d4d 100644 --- a/src/agent_env/env/gateway/gateway.py +++ b/src/agent_env/env/gateway/gateway.py @@ -38,8 +38,8 @@ # Relative import — gateway runs as a standalone container with no agent_env.* from .constants import ( AGENT_ENV_ROLE_HEADER, - AGENT_ENV_ROLE_META_KEY, # the server module serves the whole vocabulary, used in this file or not - AGENT_ENV_SESSION_META_KEY, + AGENT_ENV_ROLE_META_KEY, # noqa: F401 (the server module serves the whole vocabulary, used in this file or not) + AGENT_ENV_SESSION_META_KEY, # noqa: F401 CARD_FETCH_TIMEOUT_S, CHILD_DISCOVERY_TIMEOUT_S, DATA_PLANE_LOAD_TIMEOUT_MAX_S, diff --git a/src/agent_env/env/legacy_protocol.py b/src/agent_env/env/legacy_protocol.py index 47f951ba..e9533a84 100644 --- a/src/agent_env/env/legacy_protocol.py +++ b/src/agent_env/env/legacy_protocol.py @@ -135,7 +135,7 @@ async def reset_via_mcp_tool( reset_done = True except BaseExceptionGroup as eg: if reset_done: - logger.info(f"load_environment_artifact: succeeded (ignoring cleanup ExceptionGroup)") + logger.info("load_environment_artifact: succeeded (ignoring cleanup ExceptionGroup)") break logger.info(f"load_environment_artifact attempt {attempt + 1}/{max_retries} failed: {eg}") if attempt < max_retries - 1: diff --git a/src/agent_env/explorer/routers/runs.py b/src/agent_env/explorer/routers/runs.py index 6ab30ab6..3241e18e 100644 --- a/src/agent_env/explorer/routers/runs.py +++ b/src/agent_env/explorer/routers/runs.py @@ -17,7 +17,7 @@ from fastapi import APIRouter, HTTPException, Query from pydantic import BaseModel, ConfigDict -from agent_env.config import get_config, get_runner +from agent_env.config import get_runner from agent_env.explorer.entity_ids import EntityId from agent_env.explorer.routers.common import PaginatedResponse, docs from agent_env.runner.runner import RunStatus diff --git a/src/agent_env/task/store.py b/src/agent_env/task/store.py index 7ea6c3d9..8db870a7 100644 --- a/src/agent_env/task/store.py +++ b/src/agent_env/task/store.py @@ -554,7 +554,6 @@ def _mutate(doc: dict) -> UpdateSpec: undone_seqs.clear() undone_seqs.update({e["step_id"]: e["seq"] for e in entries if e["step_id"] in step_ids}) before = doc.get("completed_steps", []) - completed_ids = {c.get("step_id") for c in before} if not any(e["step_id"] == _SEED_STEP_ID for e in entries): raise ValueError(f"instance {instance_id!r} has no journal seed (pre-journal or unseeded); cannot undo") journaled = {e["step_id"] for e in entries} diff --git a/src/agent_env/task_step/context_ops.py b/src/agent_env/task_step/context_ops.py index c7403f01..e5301847 100644 --- a/src/agent_env/task_step/context_ops.py +++ b/src/agent_env/task_step/context_ops.py @@ -10,10 +10,13 @@ import dataclasses import types from dataclasses import dataclass, field -from typing import Any, Union, get_args, get_origin, get_type_hints +from typing import TYPE_CHECKING, Any, Union, get_args, get_origin, get_type_hints from agent_env.task_step.context import PromptResponse, TaskStepContext, _REDACTED_KEYS, _strip_redacted_keys +if TYPE_CHECKING: + from agent_env.store.document_store import UpdateSpec + @dataclass class ContextUpdateOps: diff --git a/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_peer_agents.py b/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_peer_agents.py index 38f48c66..58bb189a 100644 --- a/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_peer_agents.py +++ b/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_peer_agents.py @@ -44,7 +44,7 @@ async def execute(self, context: TaskStepContext) -> TaskStepContext: raise RuntimeError(f"VerifyA2APeerAgentsStep: no deployed agent named '{TaskStep.DEFAULT_AGENT_NAME}' in context") a2a_url = deployed.a2a_url or deployed.api_url if not a2a_url: - raise RuntimeError(f"VerifyA2APeerAgentsStep: deployed agent has no a2a_url") + raise RuntimeError("VerifyA2APeerAgentsStep: deployed agent has no a2a_url") extension = A2AAgent.find_extension(deployed.a2a_card or {}, A2AAgent.EXT_PEER_AGENTS) extension_advertised = extension is not None diff --git a/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_system_prompt.py b/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_system_prompt.py index f3994733..ecb8c27e 100644 --- a/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_system_prompt.py +++ b/src/agent_env/task_step/task_steps/a2a_agent_validator/verify_a2a_system_prompt.py @@ -84,7 +84,6 @@ async def execute(self, context: TaskStepContext) -> TaskStepContext: deployed = next((a for a in context.deployed_agents), None) if deployed is None: raise RuntimeError("No deployed agent found in context") - agent = A2AAgent.get(self.a2a_agent_id, self.a2a_agent_version) config_ext = A2AAgent.find_extension(deployed.a2a_card or {}, A2AAgent.EXT_AGENT_CONFIG) if config_ext is None: diff --git a/src/agent_env/task_step/task_steps/install_agent.py b/src/agent_env/task_step/task_steps/install_agent.py index ca7c1eb9..ac64413d 100644 --- a/src/agent_env/task_step/task_steps/install_agent.py +++ b/src/agent_env/task_step/task_steps/install_agent.py @@ -17,7 +17,7 @@ import logging import shlex from datetime import datetime, timezone -from typing import Any, Callable, ClassVar, Optional +from typing import Callable, ClassVar, Optional import httpx diff --git a/src/agent_env/task_step/task_steps/load_artifact.py b/src/agent_env/task_step/task_steps/load_artifact.py index a0c64e93..0f1ad503 100644 --- a/src/agent_env/task_step/task_steps/load_artifact.py +++ b/src/agent_env/task_step/task_steps/load_artifact.py @@ -10,7 +10,7 @@ import shlex import uuid from dataclasses import dataclass -from typing import Any, Callable, ClassVar, Optional +from typing import Callable, ClassVar, Optional from urllib.parse import unquote, urlparse from agent_env.providers.sandbox_providers.sandbox_provider import reachable_url diff --git a/src/agent_env/task_step/task_steps/prompt_agent.py b/src/agent_env/task_step/task_steps/prompt_agent.py index d0e7185c..1b0c3062 100644 --- a/src/agent_env/task_step/task_steps/prompt_agent.py +++ b/src/agent_env/task_step/task_steps/prompt_agent.py @@ -620,7 +620,7 @@ def record_turn() -> None: user_msg = (user_result.get("status") or {}).get("message") or {} current_user_parts = user_msg.get("parts") or [] if not current_user_parts: - logger.warning(f"user_a2a_url returned no parts; ending multi-turn") + logger.warning("user_a2a_url returned no parts; ending multi-turn") conversation_store.mark_closed(conversation_id) break diff --git a/src/agent_env/task_step/task_steps/verifiers/rubrics_verifier.py b/src/agent_env/task_step/task_steps/verifiers/rubrics_verifier.py index 7f8d5a3c..76248307 100644 --- a/src/agent_env/task_step/task_steps/verifiers/rubrics_verifier.py +++ b/src/agent_env/task_step/task_steps/verifiers/rubrics_verifier.py @@ -18,7 +18,7 @@ from agent_env.a2a_agent.staging import transfer_store from agent_env.config import get_config from agent_env.config.model import ModelParam -from agent_env.task_step.context import TaskStepContext, dual_keyed +from agent_env.task_step.context import PromptResponse, TaskStepContext, dual_keyed from agent_env.task_step.task_steps.verifiers.judge_utils.judge_output_format import ( SCREENSHOT_GROUNDING, JudgeOutputFormat, diff --git a/src/agent_env/task_step/task_steps/verifiers/run_container_unit_tests_verifier.py b/src/agent_env/task_step/task_steps/verifiers/run_container_unit_tests_verifier.py index e7c34531..bc092db1 100644 --- a/src/agent_env/task_step/task_steps/verifiers/run_container_unit_tests_verifier.py +++ b/src/agent_env/task_step/task_steps/verifiers/run_container_unit_tests_verifier.py @@ -203,7 +203,6 @@ def _resolve_command(self, context: TaskStepContext) -> tuple[str, dict[str, str return command, extra_env async def execute(self, context: TaskStepContext) -> TaskStepContext: - from agent_env.artifact.artifacts.file import FileArtifact from agent_env.providers.sandbox_providers.sandbox_provider import ( build_sandbox_provider, get_sandbox_provider, diff --git a/tst/data/base_mcp/base_service.py b/tst/data/base_mcp/base_service.py index c3143fe2..0ddf29b7 100644 --- a/tst/data/base_mcp/base_service.py +++ b/tst/data/base_mcp/base_service.py @@ -6,7 +6,6 @@ """ import os -from datetime import datetime from typing import Annotated, Any, Optional, TYPE_CHECKING from mcp.server.fastmcp import FastMCP diff --git a/tst/data/email_mcp/database.py b/tst/data/email_mcp/database.py index 016bbb08..c0dd21ae 100644 --- a/tst/data/email_mcp/database.py +++ b/tst/data/email_mcp/database.py @@ -16,14 +16,13 @@ import importlib.util from datetime import datetime from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional from sqlalchemy import ( Boolean, Float, String, Text, - Enum as SQLEnum, desc, ) from sqlalchemy.orm import ( diff --git a/tst/data/email_mcp/email_service.py b/tst/data/email_mcp/email_service.py index 0ac8857c..d4df77d5 100644 --- a/tst/data/email_mcp/email_service.py +++ b/tst/data/email_mcp/email_service.py @@ -10,7 +10,6 @@ import sys import importlib.util import time -import uuid from pathlib import Path from typing import Annotated, List, Optional diff --git a/tst/data/email_mcp/models.py b/tst/data/email_mcp/models.py index c7f14520..7f7a3811 100644 --- a/tst/data/email_mcp/models.py +++ b/tst/data/email_mcp/models.py @@ -6,7 +6,6 @@ """ from dataclasses import dataclass, field -from datetime import datetime from enum import Enum from typing import Any, Dict, List, Optional import uuid diff --git a/tst/data/slack_mcp/slack_service.py b/tst/data/slack_mcp/slack_service.py index 9e5c4da4..fb607b46 100644 --- a/tst/data/slack_mcp/slack_service.py +++ b/tst/data/slack_mcp/slack_service.py @@ -342,7 +342,6 @@ def add_message( Status: Not implemented in v0. Future endpoint to persist messages and update indices. """ - error = SlackError(error="not_implemented") return json.dumps( { "ok": False, diff --git a/tst/data/slack_website/backend/api/routes.py b/tst/data/slack_website/backend/api/routes.py index 21d30dc6..49aab2be 100644 --- a/tst/data/slack_website/backend/api/routes.py +++ b/tst/data/slack_website/backend/api/routes.py @@ -5,7 +5,7 @@ import os from fastapi import APIRouter, HTTPException, Query from fastapi.responses import JSONResponse -from typing import Optional, List +from typing import Optional from schemas import ( # User schemas @@ -36,8 +36,6 @@ # Health schemas HealthResponse, StatsResponse, - # Error schemas - ErrorResponse, ) from db_extensions import ExtendedDatabase, CURRENT_USER_ID diff --git a/tst/data/slack_website/backend/config.py b/tst/data/slack_website/backend/config.py index 32bb0a24..ea5cc1d7 100644 --- a/tst/data/slack_website/backend/config.py +++ b/tst/data/slack_website/backend/config.py @@ -2,7 +2,6 @@ Application configuration. """ import os -from typing import Optional class Settings: diff --git a/tst/data/slack_website/backend/db_extensions.py b/tst/data/slack_website/backend/db_extensions.py index e2ae7a4d..d4fa65f8 100644 --- a/tst/data/slack_website/backend/db_extensions.py +++ b/tst/data/slack_website/backend/db_extensions.py @@ -23,16 +23,12 @@ # Import from MCP server (DO NOT MODIFY these source files) try: - from database import SlackDatabase, UserTable, ChannelTable, MessageTable + from database import SlackDatabase, UserTable, MessageTable from models import ( User, Channel, Message, - ChannelType, - MessageType, generate_slack_ts, - ts_to_datetime, - datetime_to_ts, ) IMPORTS_AVAILABLE = True TABLES_AVAILABLE = True diff --git a/tst/env/task_step/verify_a2a_modalities_test.py b/tst/env/task_step/verify_a2a_modalities_test.py index fa705b1f..5a05f65d 100644 --- a/tst/env/task_step/verify_a2a_modalities_test.py +++ b/tst/env/task_step/verify_a2a_modalities_test.py @@ -3,8 +3,6 @@ import asyncio from unittest.mock import MagicMock, patch -import pytest - from agent_env.task_step.context import PromptResponse, TaskStepContext from agent_env.task_step.task_steps.a2a_agent_validator.verify_a2a_modalities import ( VerifyA2AModalitiesStep, diff --git a/tst/integration/artifact/artifacts/environment_artifact_test.py b/tst/integration/artifact/artifacts/environment_artifact_test.py index d3bc7615..95f10187 100644 --- a/tst/integration/artifact/artifacts/environment_artifact_test.py +++ b/tst/integration/artifact/artifacts/environment_artifact_test.py @@ -223,7 +223,7 @@ def test_get_file_artifact_returns_pinned_version_after_republish(self): def test_legacy_doc_falls_back_to_latest(self, caplog): """Pre-pinning EnvironmentArtifact (only file_artifact_id) must still load.""" file_id = _unique_id("svc_legacy_file") - file_v1 = FileArtifact.put( + FileArtifact.put( id=file_id, description="v1", file_path=str(EMAIL_ARTIFACT_PATH), diff --git a/tst/integration/env/envs/build_context_local_test.py b/tst/integration/env/envs/build_context_local_test.py index 8b6cffde..abd4cb35 100644 --- a/tst/integration/env/envs/build_context_local_test.py +++ b/tst/integration/env/envs/build_context_local_test.py @@ -19,7 +19,7 @@ from agent_env.providers.sandbox_providers import sandbox from agent_env.providers.sandbox_providers.local_sandbox import LocalSandbox from agent_env.utils.docker_build import normalize_platform -from tst.integration.env.envs.server_env_local_test import local_stack # noqa: F401 (fixture) +from tst.integration.env.envs.server_env_local_test import local_stack as local_stack from tst.integration.store.local_parallel_deploy_test import _docker, _seed_bootstrap_envs pytestmark = [pytest.mark.integration, pytest.mark.int_test_slow] diff --git a/tst/integration/env/envs/multi_env_local_test.py b/tst/integration/env/envs/multi_env_local_test.py index a8dcc3a0..ce5dc5e0 100644 --- a/tst/integration/env/envs/multi_env_local_test.py +++ b/tst/integration/env/envs/multi_env_local_test.py @@ -18,7 +18,7 @@ from agent_env.env.envs.mcp_server import MCPServerEnv from agent_env.env.envs.multi_env import MultiEnv from tst.integration.env.envs.server_env_local_test import _put_items_image -from tst.integration.store.local_parallel_deploy_test import _docker, _seed_bootstrap_envs, local_stack # noqa: F401 (fixture) +from tst.integration.store.local_parallel_deploy_test import _docker, _seed_bootstrap_envs, local_stack as local_stack pytestmark = [pytest.mark.integration, pytest.mark.int_test_slow] diff --git a/tst/integration/env/gateway/gateway_test.py b/tst/integration/env/gateway/gateway_test.py index 4b326a12..4ae363a9 100644 --- a/tst/integration/env/gateway/gateway_test.py +++ b/tst/integration/env/gateway/gateway_test.py @@ -1169,7 +1169,7 @@ async def assert_empty_via_step(client, gateway_url, tools, tool_names): # Verify schema in /step list_tools response list_emails_tool = next(t for t in tools if t["name"] == "list_emails") - assert "folder_name" in str(list_emails_tool["parameters"]), f"Expected folder_name in schema via /step" + assert "folder_name" in str(list_emails_tool["parameters"]), "Expected folder_name in schema via /step" resp = await _step_call_tool(client, gateway_url, "list_emails", {"folder_name": "INBOX"}) content_text = _step_content_text(resp) @@ -1192,7 +1192,7 @@ async def assert_empty_via_step(client, gateway_url, tools, tool_names): assert "gateway" not in server_names # no websites configured slack_server = next(s for s in state["mcp_servers"] if s["name"] == "slack") assert any(t["name"] == "channels_list" for t in slack_server["tools"]) - assert "changelog_id" in state, f"Expected changelog_id in /state response" + assert "changelog_id" in state, "Expected changelog_id in /state response" load_result = await multi_env.load_environment_universe_artifact(environment_universe_artifact) @@ -1583,7 +1583,7 @@ async def _verify_list_tools(mcp_url: str, tool_verifier_callback: callable): if assertion_errors: raise if verified: - logger.info(f" Verified (ignoring cleanup error)") + logger.info(" Verified (ignoring cleanup error)") break logger.info(f" Attempt {attempt + 1} failed: {type(eg).__name__}") if attempt < max_retries - 1: @@ -1663,7 +1663,7 @@ async def test_load_from_snapshot(multi_env, environment_universe_artifact): result = await multi_env.deploy() # Load universe — should use the snapshot created by test_snapshot_cli - load_result = await multi_env.load_environment_universe_artifact(environment_universe_artifact) + await multi_env.load_environment_universe_artifact(environment_universe_artifact) # Verify data was loaded correctly via MCP tools async def assert_loaded_data(session, tools_result, tool_names): @@ -1747,7 +1747,7 @@ async def assert_loaded_via_step(client, gateway_url, tools, tool_names): response = await client.get(f"{result.gateway_url}/state", timeout=30) response.raise_for_status() state = response.json() - assert "changelog_id" in state, f"Expected changelog_id in /state response" + assert "changelog_id" in state, "Expected changelog_id in /state response" assert isinstance(state["changelog_id"], int) and state["changelog_id"] > 0, ( f"Expected positive changelog_id in /state after writes, got {state['changelog_id']}" ) diff --git a/tst/integration/env/task_step/task_steps_test.py b/tst/integration/env/task_step/task_steps_test.py index e586538c..0e128786 100644 --- a/tst/integration/env/task_step/task_steps_test.py +++ b/tst/integration/env/task_step/task_steps_test.py @@ -1,7 +1,6 @@ import asyncio import json import logging -import subprocess import uuid import dataclasses from dataclasses import dataclass @@ -22,7 +21,7 @@ from agent_env.env.envs.service_db import ServiceDBEnv from agent_env.config import get_config from agent_env.task import Task, TaskStepStatus -from agent_env.task_step import AddSkillsTaskStep, BuildMcpCliTaskStep, DeployAgentTaskStep, DeployEnvTaskStep, EnvOutcomeVerifierTaskStep, LoadArtifactTaskStep, PromptAgentTaskStep, RubricsVerifierTaskStep, TaskStep, TaskStepContext, VerifyMCPToolSchemaTaskStep +from agent_env.task_step import AddSkillsTaskStep, BuildMcpCliTaskStep, DeployAgentTaskStep, DeployEnvTaskStep, EnvOutcomeVerifierTaskStep, LoadArtifactTaskStep, PromptAgentTaskStep, RubricsVerifierTaskStep, TaskStep, TaskStepContext from agent_env.task_step.task_step import TaskStepDependency from agent_env.a2a_agent import A2AAgent, conversation_store from agent_env.a2a_agent.object_transfer import trajectory_mode @@ -1158,7 +1157,7 @@ async def _verify_list_tools(mcp_url: str, tool_verifier_callback: callable): if assertion_errors: raise if verified: - logger.info(f" Verified (ignoring cleanup error)") + logger.info(" Verified (ignoring cleanup error)") break logger.info(f" Attempt {attempt + 1} failed: {type(eg).__name__}") if attempt < max_retries - 1: diff --git a/tst/integration/task_step/test_register_env_triggers_local.py b/tst/integration/task_step/test_register_env_triggers_local.py index 557c1ba9..f62c70da 100644 --- a/tst/integration/task_step/test_register_env_triggers_local.py +++ b/tst/integration/task_step/test_register_env_triggers_local.py @@ -22,7 +22,7 @@ from agent_env.task_step.context import DeployedAgent, TaskStepContext from agent_env.task_step.task_steps.register_env_triggers import RegisterEnvTriggersStep from tst.integration.env.envs.server_env_local_test import _put_items_image -from tst.integration.store.local_parallel_deploy_test import _seed_bootstrap_envs, local_stack # noqa: F401 (fixture) +from tst.integration.store.local_parallel_deploy_test import _seed_bootstrap_envs, local_stack as local_stack pytestmark = [pytest.mark.integration, pytest.mark.int_test_slow] diff --git a/tst/unit/a2a_agent/deploy_cleanup_test.py b/tst/unit/a2a_agent/deploy_cleanup_test.py index 4b5b584c..282cfe78 100644 --- a/tst/unit/a2a_agent/deploy_cleanup_test.py +++ b/tst/unit/a2a_agent/deploy_cleanup_test.py @@ -2,7 +2,6 @@ made it into a run's context doesn't outlive it.""" import asyncio -import types import pytest diff --git a/tst/unit/a2a_agent/protocol_test.py b/tst/unit/a2a_agent/protocol_test.py index 70bd4261..318edc4d 100644 --- a/tst/unit/a2a_agent/protocol_test.py +++ b/tst/unit/a2a_agent/protocol_test.py @@ -284,7 +284,7 @@ def answer(method, request, agent): _disconnected(request, agent) return _task("completed" if agent.now > 50 else "working") - agent = _Agent(monkeypatch, answer) + _Agent(monkeypatch, answer) result = await poll_a2a_task("http://agent", "t-1", 1200, 2, sandbox_id="sb-1") diff --git a/tst/unit/a2a_agent/validator_trajectory_dag_test.py b/tst/unit/a2a_agent/validator_trajectory_dag_test.py index cc58b82b..32298869 100644 --- a/tst/unit/a2a_agent/validator_trajectory_dag_test.py +++ b/tst/unit/a2a_agent/validator_trajectory_dag_test.py @@ -326,7 +326,6 @@ def capture_task_put(**kwargs): async def noop(*_args, **_kwargs) -> None: return None - monkeypatch.setattr("agent_env.a2a_agent.validator.get_config", lambda: FakeConfig()) monkeypatch.setattr(Task, "put", capture_task_put) monkeypatch.setattr( A2AAgentValidator, diff --git a/tst/unit/bundle/materialize_test.py b/tst/unit/bundle/materialize_test.py index 3a6bb50d..40779d95 100644 --- a/tst/unit/bundle/materialize_test.py +++ b/tst/unit/bundle/materialize_test.py @@ -6,7 +6,6 @@ import sys import textwrap import time -from pathlib import Path from typing import Literal import pytest diff --git a/tst/unit/config/test_describe.py b/tst/unit/config/test_describe.py index f71b118a..f630636f 100644 --- a/tst/unit/config/test_describe.py +++ b/tst/unit/config/test_describe.py @@ -98,7 +98,9 @@ def test_resolving_and_describing_a_bare_install_create_nothing(tmp_path): def test_a_config_file_is_reported_as_the_source_with_its_path(tmp_path): path = _write_config(tmp_path, MONGO_TOML) - sections = _sections(describe_config()) + report = describe_config() + assert report.config_path == path + sections = _sections(report) assert sections["document"].impl_name == "MongoDocumentStore" assert sections["document"].winner.where == "[stores.document]" assert sections["document"].winner.kind == "file" diff --git a/tst/unit/env/gateway/rest_proxy_stream_test.py b/tst/unit/env/gateway/rest_proxy_stream_test.py index 7d6bbfd1..caac20b0 100644 --- a/tst/unit/env/gateway/rest_proxy_stream_test.py +++ b/tst/unit/env/gateway/rest_proxy_stream_test.py @@ -294,7 +294,6 @@ class _Boom(Exception): pass up = _Upstream([b"a" * 1024, b"b" * 1024], headers={"content-length": "2048"}) - real = up.handler def handler(request): async def body(): diff --git a/tst/unit/env/gateway/role_forwarding_test.py b/tst/unit/env/gateway/role_forwarding_test.py index 619ed1bd..10b8127a 100644 --- a/tst/unit/env/gateway/role_forwarding_test.py +++ b/tst/unit/env/gateway/role_forwarding_test.py @@ -14,7 +14,6 @@ from mcp.types import CONNECTION_CLOSED, CallToolResult, ErrorData, TextContent, Tool as MCPTool from agent_env.env.gateway import AGENT_ENV_ROLE_META_KEY, AGENT_ENV_SESSION_META_KEY, InternalMCPServer -from agent_env.env.gateway import gateway as gateway_module from agent_env.env.gateway.caller import Caller from agent_env.env.gateway.constants import DEFAULT_ROLE from agent_env.env.gateway.gateway import GATEWAY_TRAJECTORY_FILE, Gateway, _call_never_reached_child, _is_dead_session diff --git a/tst/unit/env/test_snapshot_fingerprint.py b/tst/unit/env/test_snapshot_fingerprint.py index b78e22cb..00aba13d 100644 --- a/tst/unit/env/test_snapshot_fingerprint.py +++ b/tst/unit/env/test_snapshot_fingerprint.py @@ -10,8 +10,6 @@ from datetime import datetime, timezone from unittest.mock import MagicMock -import pytest - from agent_env.env.snapshot_store import ( ENV_SNAPSHOTS_COLLECTION, EnvSnapshotStore, diff --git a/tst/unit/providers/env_providers/env_gateway_provider_test.py b/tst/unit/providers/env_providers/env_gateway_provider_test.py index 8497800b..a8d3ecc0 100644 --- a/tst/unit/providers/env_providers/env_gateway_provider_test.py +++ b/tst/unit/providers/env_providers/env_gateway_provider_test.py @@ -21,7 +21,7 @@ from pytest_socket import enable_socket from agent_env.artifact.artifacts.docker_image import DockerImageArtifact -from agent_env.env.env import DeployedEnv, DeployedGatewayEnv, _mcp_url +from agent_env.env.env import DeployedGatewayEnv, _mcp_url from agent_env.env.envs.mcp_server import MCPServerEnv from agent_env.env.envs.multi_env import MultiEnv from agent_env.env.envs.service_db import SERVICE_DB_PORT @@ -44,10 +44,10 @@ from agent_env.providers.env_state import LocalPostgresStateProvider from agent_env.config import get_config, set_document_store from agent_env.store import EcrImageStore, NotFoundError -from tst.unit.providers.env_state.fakes import ( # noqa: F401 (fixture) +from tst.unit.providers.env_state.fakes import ( EXTERNAL_READINESS_SERVICE, EXTERNAL_STATE_TYPE, - registered_external_provider, + registered_external_provider as registered_external_provider, ) from tst.util.sandbox_providers import CONTAINERS, VMS_AND_CONTAINERS @@ -925,7 +925,7 @@ async def test_build_local_store_no_services(): async def _stand_up(spec): return "servicedb" - spec = await gp._build_local_store([], _stand_up) + await gp._build_local_store([], _stand_up) assert isinstance(gp._state_instance, EnvStateInstance) assert gp._state_instance.state_type == LOCAL_POSTGRES_STATE_TYPE assert gp._state_instance.metadata == {"host": "servicedb"} @@ -1015,7 +1015,6 @@ def test_compose_remote_renders_probe_and_points_at_remote(): """External backend: no servicedb/pgweb/db-mcp store containers, but the backend's OWN readiness probe is rendered, clients depend_on it, and per-service DATABASE_URL + gateway SERVICE_DB_URL point at the remote run-db handle.""" - from agent_env.env.envs.service_db import ServiceDBConfig from agent_env.providers.env_state import EnvStateInstance from tst.unit.providers.env_state.fakes import ExternalDbStateProvider diff --git a/tst/unit/providers/sandbox_providers/local_sandbox_test.py b/tst/unit/providers/sandbox_providers/local_sandbox_test.py index f98ff7c8..5088d276 100644 --- a/tst/unit/providers/sandbox_providers/local_sandbox_test.py +++ b/tst/unit/providers/sandbox_providers/local_sandbox_test.py @@ -21,7 +21,6 @@ from agent_env.store.routing import LocalRunObjectStore from agent_env.task_step.task_steps.run_code import RunCodeTaskStep from agent_env.a2a_agent import a2a_agent as a2a_agent_module -from agent_env.a2a_agent.a2a_agent import A2AAgent from agent_env.artifact.artifacts.docker_image import DockerImageArtifact from tst.unit.store.fakes import FakeObjectStore diff --git a/tst/unit/providers/sandbox_providers/test_reachability_contributions.py b/tst/unit/providers/sandbox_providers/test_reachability_contributions.py index e057a33b..e22b6e5c 100644 --- a/tst/unit/providers/sandbox_providers/test_reachability_contributions.py +++ b/tst/unit/providers/sandbox_providers/test_reachability_contributions.py @@ -13,7 +13,7 @@ import pytest -from agent_env.config import ENV_REF_PREFIX, reset_config +from agent_env.config import reset_config from agent_env.providers.sandbox_providers import sandbox_provider from agent_env.providers.sandbox_providers.local_sandbox import LocalSandboxProvider from agent_env.providers.sandbox_providers.sandbox import Sandbox diff --git a/tst/unit/runner/local_runner_test.py b/tst/unit/runner/local_runner_test.py index f3a21204..a25541e7 100644 --- a/tst/unit/runner/local_runner_test.py +++ b/tst/unit/runner/local_runner_test.py @@ -213,7 +213,7 @@ async def block(_kw): _install_task(monkeypatch, task) runner = LocalRunner(workers=1) await runner.start() - blocker = await runner.submit("t1", 1) + await runner.submit("t1", 1) await asyncio.wait_for(started.wait(), 2) # blocker holds the one slot waiting = await runner.submit("t1", 1) # no free slot → QUEUED diff --git a/tst/unit/store/local_object_store_test.py b/tst/unit/store/local_object_store_test.py index a79ce5a8..55aecba7 100644 --- a/tst/unit/store/local_object_store_test.py +++ b/tst/unit/store/local_object_store_test.py @@ -5,7 +5,6 @@ """ import errno -import hashlib import os import shutil import subprocess diff --git a/tst/unit/task_step/retry_test.py b/tst/unit/task_step/retry_test.py index d67f4914..4d7341d2 100644 --- a/tst/unit/task_step/retry_test.py +++ b/tst/unit/task_step/retry_test.py @@ -23,7 +23,7 @@ import agent_env.task.task as task_module import agent_env.task.store as store_mod -from agent_env.env.env import DeployedEnv, DeployedGatewayEnv +from agent_env.env.env import DeployedGatewayEnv from agent_env.store import LocalSqliteDocumentStore from agent_env.store.document_store import Filter from agent_env.task.step_journal import _SCHEDULER_STEP_ID, _SEED_STEP_ID, commit_ordered, replay_context diff --git a/tst/unit/task_step/test_agent_model_precedence.py b/tst/unit/task_step/test_agent_model_precedence.py index 3cb9c4b7..11582e8f 100644 --- a/tst/unit/task_step/test_agent_model_precedence.py +++ b/tst/unit/task_step/test_agent_model_precedence.py @@ -48,7 +48,6 @@ async def test_install_agent_writes_default_agent_model_not_agent_model(): agent = MagicMock() agent.metadata = {"default_model": "gpt-5.3-codex"} context = TaskStepContext() - step = InstallAgentTaskStep(id="i", version=None, sandbox_name="sb", a2a_agent_id="codex-cli") with patch("agent_env.a2a_agent.A2AAgent.get", return_value=agent), \ patch.object(InstallAgentTaskStep, "_wait_for_agent_card", AsyncMock(return_value={"name": "Codex"})), \ diff --git a/uv.lock b/uv.lock index 7661f7b9..bae2992c 100644 --- a/uv.lock +++ b/uv.lock @@ -87,6 +87,7 @@ dev = [ { name = "pytest-timeout" }, { name = "pytest-xdist" }, { name = "requests" }, + { name = "ruff" }, { name = "sail" }, { name = "tenki", extra = ["async"] }, { name = "tensorlake" }, @@ -149,6 +150,7 @@ requires-dist = [ { name = "python-multipart", specifier = ">=0.0.13" }, { name = "pyyaml", specifier = ">=6.0" }, { name = "requests", marker = "extra == 'gcp'", specifier = ">=2.31" }, + { name = "ruff", marker = "extra == 'dev'", specifier = "==0.16.10" }, { name = "sail", marker = "extra == 'sail'", specifier = "~=0.12.8" }, { name = "starlette", specifier = ">=0.40" }, { name = "tenki", extras = ["async"], marker = "extra == 'tenki'", specifier = "~=1.4.1" }, @@ -3319,6 +3321,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" }, ] +[[package]] +name = "ruff" +version = "0.16.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/49/23802c45f093eb14bde54b141d2b2f058edfa63a06db7beed047308cc08f/ruff-0.16.10.tar.gz", hash = "sha256:eff4728c4eaae93f0955cd264d24b2ab348e74bf59986ccf282ba6dc16b3b017", size = 4958724, upload-time = "2026-10-01T18:03:21.697Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/21/ebce22e1d90cdb2cd691026b9c6e9bec6499f0b396089481755b5d49efff/ruff-0.16.10-py3-none-linux_armv6l.whl", hash = "sha256:488b0fe3f3574210e5cf80d9f59b9e3ab17a127a8155de3f307b392589cfb511", size = 10095557, upload-time = "2026-10-01T18:02:36.072Z" }, + { url = "https://files.pythonhosted.org/packages/cb/98/a54de85876a8b2612bfa0d84c7b9abfb39c6a3354aee7800b09c1649b9e3/ruff-0.16.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e748ff95c934c4e978783b8e687bc174e7bd84e8ad24e3243e1ecfcda5e0282d", size = 10340577, upload-time = "2026-10-01T18:02:39.258Z" }, + { url = "https://files.pythonhosted.org/packages/9f/16/1a5a4a2657effe4806110f2b907313802f1367fcdbb29e8122766e407fab/ruff-0.16.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3031a4a2e8e7b8a46f70be45f198c35a11ece509a94b80334d8d397a33c67550", size = 9774282, upload-time = "2026-10-01T18:02:41.79Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/470085af734da396e68cd80fb0a3e7c109a459716ae59588c0f6fab8a17d/ruff-0.16.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:494401c86df4c4c25f69b9419605d944467ee98c42fb6ad405ef4fa40b8fb67d", size = 9920895, upload-time = "2026-10-01T18:02:44.458Z" }, + { url = "https://files.pythonhosted.org/packages/57/de/f10cffe4f88a37ea6615ec460f01bf76f0bc1477737a35d9ee61a630a78b/ruff-0.16.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d203abc0ff2b773ee33d00ab8df0bb67046fbc7c07b119332f08b9b345cf8221", size = 9902707, upload-time = "2026-10-01T18:02:47.041Z" }, + { url = "https://files.pythonhosted.org/packages/ff/44/3fdcedf83ae60ef837dd239170e480dce606a9142cfa2db911afdf855fd9/ruff-0.16.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd83d1235a5258d318477bc5b576303974cbdef5df0c01a1bff14efcc23bd12a", size = 10619287, upload-time = "2026-10-01T18:02:49.485Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/02e76a5574002153618eafbb70e159468addc72a5d2c488e65cbb4639d2d/ruff-0.16.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc2610fb269fa56dd8a68669ae470fa6272902668c0fc2ebc3aa112b2633d5b8", size = 11339942, upload-time = "2026-10-01T18:02:52.008Z" }, + { url = "https://files.pythonhosted.org/packages/6b/c4/cde27d47ad8d4126c587e608c67c46e7feac11763f606d261a1bc8a489e6/ruff-0.16.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e70175e29cc94c26ea296c80e470180b744b7419026898e58f520c6ab32578e", size = 10934316, upload-time = "2026-10-01T18:02:54.811Z" }, + { url = "https://files.pythonhosted.org/packages/e4/03/17234145f302a645a123e8c3bb2411ecf4669fbc350de3b0d803230a1729/ruff-0.16.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f33f43a864a8483eebd160e713336c8bab02c934feaff0a33cf5ccb41546d09a", size = 10387968, upload-time = "2026-10-01T18:02:57.497Z" }, + { url = "https://files.pythonhosted.org/packages/71/29/2493af60240ee7644b38a4b821f5f9c3b5a4fa3178770fe1d0c685217395/ruff-0.16.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1dfc6f0088149fb6a362c1c446bcbb3fd2157b3852fe2fa68409276eab9ad9b3", size = 10537906, upload-time = "2026-10-01T18:03:00.006Z" }, + { url = "https://files.pythonhosted.org/packages/2e/9a/f56b28f3b143bb9e518c34fb89ab191b626bca8b70dbf8af0d2e2d473572/ruff-0.16.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6553498afc35f580f036030795810b9e6bcea31604b0fd9e8d352795473042e3", size = 10012938, upload-time = "2026-10-01T18:03:03.006Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c4/fca37362848ea4d4d80712df13632e645e7c7cfb1bdedf140699ac7a090b/ruff-0.16.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a3b8471dea115d37f123882be852bed13403746d3a76c11de4a19ec5f9ff5a03", size = 9897945, upload-time = "2026-10-01T18:03:05.818Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c7/e0bc57664d6e0c61fd22f620af260fe9662d7e1ddb320ea7f160e76ef165/ruff-0.16.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:92e59a70bcbd9d3a5483656da906ec28edfdacfce00afd99edb8b4e9d15644be", size = 10333134, upload-time = "2026-10-01T18:03:08.25Z" }, + { url = "https://files.pythonhosted.org/packages/21/aa/5c9f3b68737c0e4a33a1db5dfab44f7b786d96ca91a7233112ddab1e6dc2/ruff-0.16.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7ae7375f803b5520dc9f546bed7e3a0acb70b91812e9bb4b19927de22f25b77d", size = 10741702, upload-time = "2026-10-01T18:03:10.775Z" }, + { url = "https://files.pythonhosted.org/packages/78/fa/0f9c2020dc316c53d983be011720b8157cc052b97e3f4dfa7db6d0f880a6/ruff-0.16.10-py3-none-win32.whl", hash = "sha256:2a12e01cb9156c10c466f63b46eaae5ecea28dfbd21b5836353ae498e7d1349a", size = 10139176, upload-time = "2026-10-01T18:03:13.267Z" }, + { url = "https://files.pythonhosted.org/packages/99/29/cfb0df9448d4d4ad48c2de029ada9ebd71baa6da983a6c77ee6c6cd0fe82/ruff-0.16.10-py3-none-win_amd64.whl", hash = "sha256:97f2015c92aa97105b0eab19eb5d224884399281cfc5da86a92db4ab5e7fb2ca", size = 10584734, upload-time = "2026-10-01T18:03:16.006Z" }, + { url = "https://files.pythonhosted.org/packages/fc/05/c16957eb287c3fc062e032619a25868d93d408a844b725bcf514f7a378ff/ruff-0.16.10-py3-none-win_arm64.whl", hash = "sha256:25a65fe998c4e6861ec079ada5826a2fc605e6cbccbe9dcd7fac1f54e791621b", size = 10366440, upload-time = "2026-10-01T18:03:19.04Z" }, +] + [[package]] name = "s3transfer" version = "0.19.0"