From cad54a9f3e3ac346cc78bb5b2658845bcff5f36e Mon Sep 17 00:00:00 2001 From: Reinier van der Leer Date: Wed, 11 Feb 2026 17:12:43 +0100 Subject: [PATCH] eliminate more cross-imports --- .../backend/backend/api/external/v1/routes.py | 2 +- .../backend/api/features/builder/db.py | 19 +++++++----- .../backend/api/features/builder/model.py | 2 +- .../backend/api/features/builder/routes.py | 2 +- .../backend/api/features/library/db.py | 3 +- .../backend/api/features/library/model.py | 7 +++-- .../backend/backend/api/features/v1.py | 8 +++-- .../backend/backend/blocks/_base.py | 29 +++++++++---------- .../backend/backend/data/execution.py | 3 +- .../backend/backend/data/graph.py | 9 ++---- .../backend/backend/data/model.py | 7 +++++ .../backend/backend/executor/manager.py | 10 +++++-- .../backend/backend/executor/scheduler.py | 3 +- .../backend/backend/executor/utils.py | 15 +++++----- 14 files changed, 67 insertions(+), 52 deletions(-) diff --git a/autogpt_platform/backend/backend/api/external/v1/routes.py b/autogpt_platform/backend/backend/api/external/v1/routes.py index bae61124e2..8ef2da3e31 100644 --- a/autogpt_platform/backend/backend/api/external/v1/routes.py +++ b/autogpt_platform/backend/backend/api/external/v1/routes.py @@ -12,11 +12,11 @@ import backend.api.features.store.cache as store_cache import backend.api.features.store.model as store_model import backend.blocks from backend.api.external.middleware import require_permission -from backend.blocks._base import BlockInput, CompletedBlockOutput from backend.data import execution as execution_db from backend.data import graph as graph_db from backend.data import user as user_db from backend.data.auth.base import APIAuthorizationInfo +from backend.data.model import BlockInput, CompletedBlockOutput from backend.executor.utils import add_graph_execution from backend.util.settings import Settings diff --git a/autogpt_platform/backend/backend/api/features/builder/db.py b/autogpt_platform/backend/backend/api/features/builder/db.py index 7b228c043d..e8d35b0bb5 100644 --- a/autogpt_platform/backend/backend/api/features/builder/db.py +++ b/autogpt_platform/backend/backend/api/features/builder/db.py @@ -10,9 +10,14 @@ import backend.api.features.library.db as library_db import backend.api.features.library.model as library_model import backend.api.features.store.db as store_db import backend.api.features.store.model as store_model -import backend.blocks._base from backend.blocks import load_all_blocks -from backend.blocks._base import AnyBlockSchema, BlockCategory, BlockInfo, BlockSchema +from backend.blocks._base import ( + AnyBlockSchema, + BlockCategory, + BlockInfo, + BlockSchema, + BlockType, +) from backend.blocks.llm import LlmModel from backend.data.db import query_raw_with_schema from backend.integrations.providers import ProviderName @@ -22,7 +27,7 @@ from backend.util.models import Pagination from .model import ( BlockCategoryResponse, BlockResponse, - BlockType, + BlockTypeFilter, CountResponse, FilterType, Provider, @@ -88,7 +93,7 @@ def get_block_categories(category_blocks: int = 3) -> list[BlockCategoryResponse def get_blocks( *, category: str | None = None, - type: BlockType | None = None, + type: BlockTypeFilter | None = None, provider: ProviderName | None = None, page: int = 1, page_size: int = 50, @@ -669,9 +674,9 @@ async def get_suggested_blocks(count: int = 5) -> list[BlockInfo]: for block_type in load_all_blocks().values(): block: AnyBlockSchema = block_type() if block.disabled or block.block_type in ( - backend.blocks._base.BlockType.INPUT, - backend.blocks._base.BlockType.OUTPUT, - backend.blocks._base.BlockType.AGENT, + BlockType.INPUT, + BlockType.OUTPUT, + BlockType.AGENT, ): continue # Find the execution count for this block diff --git a/autogpt_platform/backend/backend/api/features/builder/model.py b/autogpt_platform/backend/backend/api/features/builder/model.py index f9b883d5bc..8aa8ed06ed 100644 --- a/autogpt_platform/backend/backend/api/features/builder/model.py +++ b/autogpt_platform/backend/backend/api/features/builder/model.py @@ -15,7 +15,7 @@ FilterType = Literal[ "my_agents", ] -BlockType = Literal["all", "input", "action", "output"] +BlockTypeFilter = Literal["all", "input", "action", "output"] class SearchEntry(BaseModel): diff --git a/autogpt_platform/backend/backend/api/features/builder/routes.py b/autogpt_platform/backend/backend/api/features/builder/routes.py index 15b922178d..091f477178 100644 --- a/autogpt_platform/backend/backend/api/features/builder/routes.py +++ b/autogpt_platform/backend/backend/api/features/builder/routes.py @@ -88,7 +88,7 @@ async def get_block_categories( ) async def get_blocks( category: Annotated[str | None, fastapi.Query()] = None, - type: Annotated[builder_model.BlockType | None, fastapi.Query()] = None, + type: Annotated[builder_model.BlockTypeFilter | None, fastapi.Query()] = None, provider: Annotated[ProviderName | None, fastapi.Query()] = None, page: Annotated[int, fastapi.Query()] = 1, page_size: Annotated[int, fastapi.Query()] = 50, diff --git a/autogpt_platform/backend/backend/api/features/library/db.py b/autogpt_platform/backend/backend/api/features/library/db.py index 1c7219cd6e..9204794595 100644 --- a/autogpt_platform/backend/backend/api/features/library/db.py +++ b/autogpt_platform/backend/backend/api/features/library/db.py @@ -12,12 +12,11 @@ import backend.api.features.store.image_gen as store_image_gen import backend.api.features.store.media as store_media import backend.data.graph as graph_db import backend.data.integrations as integrations_db -from backend.blocks._base import BlockInput from backend.data.db import transaction from backend.data.execution import get_graph_execution from backend.data.graph import GraphSettings from backend.data.includes import AGENT_PRESET_INCLUDE, library_agent_include -from backend.data.model import CredentialsMetaInput +from backend.data.model import BlockInput, CredentialsMetaInput from backend.integrations.creds_manager import IntegrationCredentialsManager from backend.integrations.webhooks.graph_lifecycle_hooks import ( on_graph_activate, diff --git a/autogpt_platform/backend/backend/api/features/library/model.py b/autogpt_platform/backend/backend/api/features/library/model.py index 69bbe85486..cf2a7cd876 100644 --- a/autogpt_platform/backend/backend/api/features/library/model.py +++ b/autogpt_platform/backend/backend/api/features/library/model.py @@ -6,9 +6,12 @@ import prisma.enums import prisma.models import pydantic -from backend.blocks._base import BlockInput from backend.data.graph import GraphModel, GraphSettings, GraphTriggerInfo -from backend.data.model import CredentialsMetaInput, is_credentials_field_name +from backend.data.model import ( + BlockInput, + CredentialsMetaInput, + is_credentials_field_name, +) from backend.util.json import loads as json_loads from backend.util.models import Pagination diff --git a/autogpt_platform/backend/backend/api/features/v1.py b/autogpt_platform/backend/backend/api/features/v1.py index 713bbaa7d6..371967eba7 100644 --- a/autogpt_platform/backend/backend/api/features/v1.py +++ b/autogpt_platform/backend/backend/api/features/v1.py @@ -41,7 +41,6 @@ from backend.api.model import ( UploadFileResponse, ) from backend.blocks import get_block, get_blocks -from backend.blocks._base import BlockInput, CompletedBlockOutput from backend.data import execution as execution_db from backend.data import graph as graph_db from backend.data.auth import api_key as api_key_db @@ -55,7 +54,12 @@ from backend.data.credit import ( set_auto_top_up, ) from backend.data.graph import GraphSettings -from backend.data.model import CredentialsMetaInput, UserOnboarding +from backend.data.model import ( + BlockInput, + CompletedBlockOutput, + CredentialsMetaInput, + UserOnboarding, +) from backend.data.notifications import NotificationPreference, NotificationPreferenceDTO from backend.data.onboarding import ( FrontendOnboardingStep, diff --git a/autogpt_platform/backend/backend/blocks/_base.py b/autogpt_platform/backend/backend/blocks/_base.py index 626b99fc9f..e70fdf76f2 100644 --- a/autogpt_platform/backend/backend/blocks/_base.py +++ b/autogpt_platform/backend/backend/blocks/_base.py @@ -1,7 +1,6 @@ import inspect import logging from abc import ABC, abstractmethod -from collections.abc import AsyncGenerator as AsyncGen from enum import Enum from typing import ( TYPE_CHECKING, @@ -21,6 +20,16 @@ import jsonref import jsonschema from pydantic import BaseModel +from backend.data.model import ( + BlockInput, + BlockOutput, + BlockOutputEntry, + Credentials, + CredentialsFieldInfo, + CredentialsMetaInput, + SchemaField, + is_credentials_field_name, +) from backend.integrations.providers import ProviderName from backend.util import json from backend.util.exceptions import ( @@ -32,30 +41,18 @@ from backend.util.exceptions import ( ) from backend.util.settings import Config -from ..data.model import ( - ContributorDetails, - Credentials, - CredentialsFieldInfo, - CredentialsMetaInput, - SchemaField, - is_credentials_field_name, -) - logger = logging.getLogger(__name__) if TYPE_CHECKING: from backend.data.execution import ExecutionContext - from backend.data.model import NodeExecutionStats + from backend.data.model import ContributorDetails, NodeExecutionStats from ..data.graph import Link app_config = Config() -BlockInput = dict[str, Any] # Input: 1 input pin consumes 1 data. -BlockOutputEntry = tuple[str, Any] # Output data should be a tuple of (name, value). -BlockOutput = AsyncGen[BlockOutputEntry, None] # Output: 1 output pin produces n data. + BlockTestOutput = BlockOutputEntry | tuple[str, Callable[[Any], bool]] -CompletedBlockOutput = dict[str, list[Any]] # Completed stream, collected as a dict. class BlockType(Enum): @@ -426,7 +423,7 @@ class Block(ABC, Generic[BlockSchemaInputType, BlockSchemaOutputType]): self, id: str = "", description: str = "", - contributors: list[ContributorDetails] = [], + contributors: list["ContributorDetails"] = [], categories: set[BlockCategory] | None = None, input_schema: Type[BlockSchemaInputType] = EmptyInputSchema, output_schema: Type[BlockSchemaOutputType] = EmptyOutputSchema, diff --git a/autogpt_platform/backend/backend/data/execution.py b/autogpt_platform/backend/backend/data/execution.py index 800edb00e3..821820f998 100644 --- a/autogpt_platform/backend/backend/data/execution.py +++ b/autogpt_platform/backend/backend/data/execution.py @@ -40,7 +40,8 @@ from pydantic import BaseModel, ConfigDict, JsonValue, ValidationError from pydantic.fields import Field from backend.blocks import get_block, get_io_block_ids, get_webhook_block_ids -from backend.blocks._base import BlockInput, BlockType, CompletedBlockOutput +from backend.blocks._base import BlockType +from backend.data.model import BlockInput, CompletedBlockOutput from backend.util import type as type_utils from backend.util.exceptions import DatabaseError from backend.util.json import SafeJson diff --git a/autogpt_platform/backend/backend/data/graph.py b/autogpt_platform/backend/backend/data/graph.py index 1de7335773..4ced05982b 100644 --- a/autogpt_platform/backend/backend/data/graph.py +++ b/autogpt_platform/backend/backend/data/graph.py @@ -24,13 +24,7 @@ from pydantic import BaseModel, BeforeValidator, Field from pydantic.fields import computed_field from backend.blocks import get_block, get_blocks -from backend.blocks._base import ( - AnyBlockSchema, - Block, - BlockInput, - BlockType, - EmptySchema, -) +from backend.blocks._base import AnyBlockSchema, Block, BlockType, EmptySchema from backend.blocks.agent import AgentExecutorBlock from backend.blocks.io import AgentInputBlock, AgentOutputBlock from backend.blocks.llm import LlmModel @@ -38,6 +32,7 @@ from backend.data.db import prisma as db from backend.data.dynamic_fields import is_tool_pin, sanitize_pin_name from backend.data.includes import MAX_GRAPH_VERSIONS_FETCH from backend.data.model import ( + BlockInput, CredentialsFieldInfo, CredentialsMetaInput, is_credentials_field_name, diff --git a/autogpt_platform/backend/backend/data/model.py b/autogpt_platform/backend/backend/data/model.py index 7bdfef059b..45601075b8 100644 --- a/autogpt_platform/backend/backend/data/model.py +++ b/autogpt_platform/backend/backend/data/model.py @@ -10,6 +10,7 @@ from typing import ( TYPE_CHECKING, Annotated, Any, + AsyncGenerator, Callable, ClassVar, Generic, @@ -168,6 +169,12 @@ T = TypeVar("T") logger = logging.getLogger(__name__) +BlockInput = dict[str, Any] # Input: 1 input pin <- 1 data. +BlockOutputEntry = tuple[str, Any] # Output data should be a tuple of (name, value). +BlockOutput = AsyncGenerator[BlockOutputEntry, None] # Output: 1 output pin -> N data. +CompletedBlockOutput = dict[str, list[Any]] # Completed stream, collected as a dict. + + class BlockSecret: def __init__(self, key: Optional[str] = None, value: Optional[str] = None): if value is not None: diff --git a/autogpt_platform/backend/backend/executor/manager.py b/autogpt_platform/backend/backend/executor/manager.py index 2446d84412..50f8bff108 100644 --- a/autogpt_platform/backend/backend/executor/manager.py +++ b/autogpt_platform/backend/backend/executor/manager.py @@ -17,7 +17,7 @@ from prometheus_client import Gauge, start_http_server from redis.asyncio.lock import Lock as AsyncRedisLock from backend.blocks import get_block -from backend.blocks._base import BlockInput, BlockOutput, BlockOutputEntry, BlockSchema +from backend.blocks._base import BlockSchema from backend.blocks.agent import AgentExecutorBlock from backend.blocks.io import AgentOutputBlock from backend.data import redis_client as redis @@ -34,7 +34,13 @@ from backend.data.execution import ( NodesInputMasks, ) from backend.data.graph import Link, Node -from backend.data.model import GraphExecutionStats, NodeExecutionStats +from backend.data.model import ( + BlockInput, + BlockOutput, + BlockOutputEntry, + GraphExecutionStats, + NodeExecutionStats, +) from backend.data.notifications import ( AgentRunData, LowBalanceData, diff --git a/autogpt_platform/backend/backend/executor/scheduler.py b/autogpt_platform/backend/backend/executor/scheduler.py index b0609827e6..3d02b34f9c 100644 --- a/autogpt_platform/backend/backend/executor/scheduler.py +++ b/autogpt_platform/backend/backend/executor/scheduler.py @@ -24,9 +24,8 @@ from dotenv import load_dotenv from pydantic import BaseModel, Field, ValidationError from sqlalchemy import MetaData, create_engine -from backend.blocks._base import BlockInput from backend.data.execution import GraphExecutionWithNodes -from backend.data.model import CredentialsMetaInput +from backend.data.model import BlockInput, CredentialsMetaInput from backend.executor import utils as execution_utils from backend.monitoring import ( NotificationJobArgs, diff --git a/autogpt_platform/backend/backend/executor/utils.py b/autogpt_platform/backend/backend/executor/utils.py index 68def74706..ff54398b68 100644 --- a/autogpt_platform/backend/backend/executor/utils.py +++ b/autogpt_platform/backend/backend/executor/utils.py @@ -9,13 +9,7 @@ from typing import Mapping, Optional, cast from pydantic import BaseModel, JsonValue, ValidationError from backend.blocks import get_block -from backend.blocks._base import ( - Block, - BlockCostType, - BlockInput, - BlockOutputEntry, - BlockType, -) +from backend.blocks._base import Block, BlockCostType, BlockType from backend.data import execution as execution_db from backend.data import graph as graph_db from backend.data import human_review as human_review_db @@ -35,7 +29,12 @@ from backend.data.execution import ( NodesInputMasks, ) from backend.data.graph import GraphModel, Node -from backend.data.model import USER_TIMEZONE_NOT_SET, CredentialsMetaInput +from backend.data.model import ( + USER_TIMEZONE_NOT_SET, + BlockInput, + BlockOutputEntry, + CredentialsMetaInput, +) from backend.data.rabbitmq import Exchange, ExchangeType, Queue, RabbitMQConfig from backend.util.clients import ( get_async_execution_event_bus,