From 0591b00ded02c0c6007aa94bf2bc8678222cd6fd Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Thu, 4 Jun 2026 10:00:10 +0200 Subject: [PATCH] refactor: reorganize models into subpackages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move models into domain subpackages (max 4 files each): - models/tool/ — tool_type, tool_instance, tool_definition_manifest - models/config/ — config_profile - models/user/ — user, user_config, ssh_key - models/project/ — project, git_repository, workspace - models/system/ — health_check, notification, instance_event, terminal_session models/__init__.py continues to re-export all symbols, so consumers using 'from src.models import X' are unaffected. Updated direct file imports across the backend to use the new paths. Quality gates: py_compile passed, ruff passed. --- apps/api/src/api/config/__init__.py | 1 + apps/api/src/api/config_profiles.py | 8 +++--- apps/api/src/api/dashboard.py | 4 +-- apps/api/src/api/git_repositories.py | 4 +-- apps/api/src/api/instance_proxy.py | 4 +-- apps/api/src/api/notifications.py | 2 +- apps/api/src/api/project/__init__.py | 1 + apps/api/src/api/projects.py | 8 +++--- apps/api/src/api/ssh_keys.py | 2 +- apps/api/src/api/system/__init__.py | 1 + apps/api/src/api/terminal.py | 6 ++-- apps/api/src/api/tool/__init__.py | 1 + apps/api/src/api/tool_definitions.py | 4 +-- apps/api/src/api/tool_instances.py | 22 +++++++-------- apps/api/src/api/tool_types.py | 2 +- apps/api/src/api/user/__init__.py | 1 + apps/api/src/api/user_config.py | 2 +- apps/api/src/api/workspace/__init__.py | 1 + apps/api/src/api/workspace_files.py | 2 +- apps/api/src/api/workspace_git.py | 2 +- apps/api/src/api/workspace_instances.py | 4 +-- apps/api/src/api/workspaces.py | 6 ++-- apps/api/src/main.py | 4 +-- apps/api/src/models/__init__.py | 28 +++++++++---------- apps/api/src/models/config/__init__.py | 5 ++++ .../src/models/{ => config}/config_profile.py | 2 +- apps/api/src/models/project/__init__.py | 7 +++++ .../models/{ => project}/git_repository.py | 2 +- apps/api/src/models/{ => project}/project.py | 4 +-- .../api/src/models/{ => project}/workspace.py | 2 +- apps/api/src/models/system/__init__.py | 8 ++++++ .../src/models/{ => system}/health_check.py | 0 .../src/models/{ => system}/instance_event.py | 0 .../src/models/{ => system}/notification.py | 0 .../models/{ => system}/terminal_session.py | 0 apps/api/src/models/tool/__init__.py | 7 +++++ .../{ => tool}/tool_definition_manifest.py | 0 .../src/models/{ => tool}/tool_instance.py | 8 +++--- apps/api/src/models/{ => tool}/tool_type.py | 3 +- apps/api/src/models/user/__init__.py | 7 +++++ apps/api/src/models/{ => user}/ssh_key.py | 0 apps/api/src/models/{ => user}/user.py | 4 +-- apps/api/src/models/{ => user}/user_config.py | 0 apps/api/src/schemas/config/__init__.py | 1 + apps/api/src/schemas/project/__init__.py | 1 + apps/api/src/schemas/system/__init__.py | 1 + apps/api/src/schemas/tool/__init__.py | 1 + apps/api/src/schemas/user/__init__.py | 1 + apps/api/src/seeds/builtin_tool_types.py | 2 +- apps/api/src/services/config/__init__.py | 1 + .../src/services/config_profile_resolver.py | 2 +- apps/api/src/services/file_service.py | 2 +- apps/api/src/services/git/__init__.py | 1 + apps/api/src/services/git_operations.py | 2 +- apps/api/src/services/health_monitor.py | 4 +-- apps/api/src/services/instance/__init__.py | 1 + apps/api/src/services/lifecycle_hooks.py | 4 +-- apps/api/src/services/notification_service.py | 2 +- apps/api/src/services/shared/__init__.py | 1 + apps/api/src/services/terminal/__init__.py | 1 + apps/api/src/services/terminal_manager.py | 2 +- apps/api/src/services/workspace_manager.py | 14 +++++----- 62 files changed, 136 insertions(+), 87 deletions(-) create mode 100644 apps/api/src/api/config/__init__.py create mode 100644 apps/api/src/api/project/__init__.py create mode 100644 apps/api/src/api/system/__init__.py create mode 100644 apps/api/src/api/tool/__init__.py create mode 100644 apps/api/src/api/user/__init__.py create mode 100644 apps/api/src/api/workspace/__init__.py create mode 100644 apps/api/src/models/config/__init__.py rename apps/api/src/models/{ => config}/config_profile.py (98%) create mode 100644 apps/api/src/models/project/__init__.py rename apps/api/src/models/{ => project}/git_repository.py (97%) rename apps/api/src/models/{ => project}/project.py (92%) rename apps/api/src/models/{ => project}/workspace.py (96%) create mode 100644 apps/api/src/models/system/__init__.py rename apps/api/src/models/{ => system}/health_check.py (100%) rename apps/api/src/models/{ => system}/instance_event.py (100%) rename apps/api/src/models/{ => system}/notification.py (100%) rename apps/api/src/models/{ => system}/terminal_session.py (100%) create mode 100644 apps/api/src/models/tool/__init__.py rename apps/api/src/models/{ => tool}/tool_definition_manifest.py (100%) rename apps/api/src/models/{ => tool}/tool_instance.py (93%) rename apps/api/src/models/{ => tool}/tool_type.py (96%) create mode 100644 apps/api/src/models/user/__init__.py rename apps/api/src/models/{ => user}/ssh_key.py (100%) rename apps/api/src/models/{ => user}/user.py (90%) rename apps/api/src/models/{ => user}/user_config.py (100%) create mode 100644 apps/api/src/schemas/config/__init__.py create mode 100644 apps/api/src/schemas/project/__init__.py create mode 100644 apps/api/src/schemas/system/__init__.py create mode 100644 apps/api/src/schemas/tool/__init__.py create mode 100644 apps/api/src/schemas/user/__init__.py create mode 100644 apps/api/src/services/config/__init__.py create mode 100644 apps/api/src/services/git/__init__.py create mode 100644 apps/api/src/services/instance/__init__.py create mode 100644 apps/api/src/services/shared/__init__.py create mode 100644 apps/api/src/services/terminal/__init__.py diff --git a/apps/api/src/api/config/__init__.py b/apps/api/src/api/config/__init__.py new file mode 100644 index 0000000..da7ff7c --- /dev/null +++ b/apps/api/src/api/config/__init__.py @@ -0,0 +1 @@ +"""Config module.""" diff --git a/apps/api/src/api/config_profiles.py b/apps/api/src/api/config_profiles.py index 5838240..007c9cd 100644 --- a/apps/api/src/api/config_profiles.py +++ b/apps/api/src/api/config_profiles.py @@ -14,10 +14,10 @@ from sqlalchemy.orm import selectinload from src.api.shared_validators import validate_env_vars as _validate_env_vars from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.config_profile import ConfigProfile, ConfigProfileInclude +from src.models import ConfigProfile, ConfigProfileInclude from src.models.project import Project -from src.models.tool_type import ToolType -from src.models.user_config import UserConfig +from src.models import ToolType +from src.models import UserConfig from src.services.config_profile_resolver import ( ConfigProfileCycleError, check_include_cycle, @@ -991,7 +991,7 @@ async def validate_git_url( env = None key_path = None if data.ssh_key_id: - from src.models.ssh_key import SSHKey + from src.models import SSHKey from src.services.ssh_keys import _get_fernet try: diff --git a/apps/api/src/api/dashboard.py b/apps/api/src/api/dashboard.py index b9059f3..2fb8203 100644 --- a/apps/api/src/api/dashboard.py +++ b/apps/api/src/api/dashboard.py @@ -5,9 +5,9 @@ from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.git_repository import GitRepository +from src.models import GitRepository from src.models.project import Project -from src.models.ssh_key import SSHKey +from src.models import SSHKey router = APIRouter(prefix="/dashboard", tags=["dashboard"]) diff --git a/apps/api/src/api/git_repositories.py b/apps/api/src/api/git_repositories.py index 0b3892d..1def6e3 100644 --- a/apps/api/src/api/git_repositories.py +++ b/apps/api/src/api/git_repositories.py @@ -17,8 +17,8 @@ from src.auth.dependencies import ( get_db_session, ) from src.config import Settings -from src.models.git_repository import GitRepository -from src.models.ssh_key import SSHKey +from src.models import GitRepository +from src.models import SSHKey from src.utils.git_files import ( commit_file, get_file_content, diff --git a/apps/api/src/api/instance_proxy.py b/apps/api/src/api/instance_proxy.py index 4145e6c..8e99ddf 100644 --- a/apps/api/src/api/instance_proxy.py +++ b/apps/api/src/api/instance_proxy.py @@ -8,8 +8,8 @@ from fastapi import APIRouter, Depends, HTTPException, Request, Response, status from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.tool_instance import ToolInstance -from src.models.tool_type import ToolType +from src.models import ToolInstance +from src.models import ToolType logger = logging.getLogger(__name__) diff --git a/apps/api/src/api/notifications.py b/apps/api/src/api/notifications.py index 9dff52c..5d51848 100644 --- a/apps/api/src/api/notifications.py +++ b/apps/api/src/api/notifications.py @@ -9,7 +9,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user, get_db_session from src.models.user import User -from src.models.user_config import UserConfig +from src.models import UserConfig from src.services.notification_service import notification_service router = APIRouter(prefix="/notifications", tags=["notifications"]) diff --git a/apps/api/src/api/project/__init__.py b/apps/api/src/api/project/__init__.py new file mode 100644 index 0000000..1ed2378 --- /dev/null +++ b/apps/api/src/api/project/__init__.py @@ -0,0 +1 @@ +"""Project module.""" diff --git a/apps/api/src/api/projects.py b/apps/api/src/api/projects.py index d68cacb..dd59fcb 100644 --- a/apps/api/src/api/projects.py +++ b/apps/api/src/api/projects.py @@ -13,10 +13,10 @@ from src.auth.dependencies import ( get_current_user_id, get_db_session, ) -from src.models.git_repository import GitRepository +from src.models import GitRepository from src.models.project import Project -from src.models.ssh_key import SSHKey -from src.models.tool_instance import ToolInstance +from src.models import SSHKey +from src.models import ToolInstance router = APIRouter(prefix="/projects", tags=["projects"]) @@ -101,7 +101,7 @@ async def list_projects( ) projects = result.scalars().all() - from src.models.workspace import Workspace + from src.models import Workspace enriched = [] for project in projects: diff --git a/apps/api/src/api/ssh_keys.py b/apps/api/src/api/ssh_keys.py index a18a96c..4d27df2 100644 --- a/apps/api/src/api/ssh_keys.py +++ b/apps/api/src/api/ssh_keys.py @@ -12,7 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import _get_user, get_current_user_id, get_db_session from src.config import Settings -from src.models.ssh_key import SSHKey +from src.models import SSHKey router = APIRouter(prefix="/ssh-keys", tags=["ssh-keys"]) diff --git a/apps/api/src/api/system/__init__.py b/apps/api/src/api/system/__init__.py new file mode 100644 index 0000000..3f55c57 --- /dev/null +++ b/apps/api/src/api/system/__init__.py @@ -0,0 +1 @@ +"""System module.""" diff --git a/apps/api/src/api/terminal.py b/apps/api/src/api/terminal.py index c2f2a8d..ce4fcd8 100644 --- a/apps/api/src/api/terminal.py +++ b/apps/api/src/api/terminal.py @@ -12,9 +12,9 @@ from sqlalchemy.ext.asyncio import AsyncSession from starlette.websockets import WebSocketDisconnect from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.terminal_session import TerminalSessionModel -from src.models.tool_instance import ToolInstance -from src.models.tool_type import ToolType +from src.models import TerminalSessionModel +from src.models import ToolInstance +from src.models import ToolType from src.services.terminal_manager import MaxSessionsExceededError, terminal_manager router = APIRouter() diff --git a/apps/api/src/api/tool/__init__.py b/apps/api/src/api/tool/__init__.py new file mode 100644 index 0000000..b05b87d --- /dev/null +++ b/apps/api/src/api/tool/__init__.py @@ -0,0 +1 @@ +"""Tool module.""" diff --git a/apps/api/src/api/tool_definitions.py b/apps/api/src/api/tool_definitions.py index a0abc33..96e28e7 100644 --- a/apps/api/src/api/tool_definitions.py +++ b/apps/api/src/api/tool_definitions.py @@ -9,8 +9,8 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.tool_definition_manifest import ToolDefinitionManifest -from src.models.tool_type import ToolType +from src.models import ToolDefinitionManifest +from src.models import ToolType from src.services.manifest_compiler import ( compile_compose, compile_dockerfile, diff --git a/apps/api/src/api/tool_instances.py b/apps/api/src/api/tool_instances.py index 7898fe2..4f384c7 100644 --- a/apps/api/src/api/tool_instances.py +++ b/apps/api/src/api/tool_instances.py @@ -30,12 +30,12 @@ from src.auth.dependencies import ( ) from src.services.event_bus import InstanceEventBus from src.services.lifecycle_hooks import publish_lifecycle_event -from src.models.config_profile import ConfigProfile -from src.models.git_repository import GitRepository +from src.models import ConfigProfile +from src.models import GitRepository from src.models.project import Project -from src.models.ssh_key import SSHKey -from src.models.tool_instance import ToolInstance -from src.models.tool_type import ToolType +from src.models import SSHKey +from src.models import ToolInstance +from src.models import ToolType from src.services.clone import check_dirty_state, clone_repository from src.services.config_profile_resolver import ( ConfigProfileCycleError, @@ -856,7 +856,7 @@ async def create_instance( workspace = None workspace_id = None if data.workspace_id: - from src.models.workspace import Workspace as WorkspaceModel + from src.models import Workspace as WorkspaceModel try: workspace_id = uuid.UUID(data.workspace_id) @@ -1056,7 +1056,7 @@ services: elif tool_type.definition_type == "manifest": # Manifest-based: generate compose only; image built lazily on start - from src.models.tool_definition_manifest import ToolDefinitionManifest + from src.models import ToolDefinitionManifest manifest_def = await session.get( ToolDefinitionManifest, tool_type.manifest_id @@ -1341,7 +1341,7 @@ async def _prepare_manifest_instance( Returns: Tuple of (image_tag, compose_content, resolved_manifest, home_dir) """ - from src.models.tool_definition_manifest import ToolDefinitionManifest + from src.models import ToolDefinitionManifest tool_type = await session.get(ToolType, instance.tool_type_id) manifest_def = await session.get(ToolDefinitionManifest, tool_type.manifest_id) @@ -1537,7 +1537,7 @@ async def start_instance( container_uid = 0 container_gid = 0 if tool_type and tool_type.definition_type == "manifest" and tool_type.manifest_id: - from src.models.tool_definition_manifest import ToolDefinitionManifest + from src.models import ToolDefinitionManifest manifest_def = await session.get(ToolDefinitionManifest, tool_type.manifest_id) if manifest_def: @@ -1724,7 +1724,7 @@ async def start_instance( # Determine repo path (workspace takes precedence) repo_path = "" if instance.workspace_id: - from src.models.workspace import Workspace as WorkspaceModel + from src.models import Workspace as WorkspaceModel workspace = await session.get(WorkspaceModel, instance.workspace_id) if workspace: @@ -2767,7 +2767,7 @@ async def get_instance_events( List of event dictionaries. """ from sqlalchemy import select - from src.models.instance_event import InstanceEvent + from src.models import InstanceEvent _user = await _get_user(session, user_id) _project = await _get_owned_project(project_id, user_id, session) diff --git a/apps/api/src/api/tool_types.py b/apps/api/src/api/tool_types.py index d669c39..65096fe 100644 --- a/apps/api/src/api/tool_types.py +++ b/apps/api/src/api/tool_types.py @@ -12,7 +12,7 @@ from src.api.tool_types_validation import ( validate_required_variables, ) from src.auth.dependencies import _get_user, get_current_user_id, get_db_session -from src.models.tool_type import ToolType +from src.models import ToolType from src.models.user import User router = APIRouter(prefix="/tool-types", tags=["tool-types"]) diff --git a/apps/api/src/api/user/__init__.py b/apps/api/src/api/user/__init__.py new file mode 100644 index 0000000..7f42956 --- /dev/null +++ b/apps/api/src/api/user/__init__.py @@ -0,0 +1 @@ +"""User module.""" diff --git a/apps/api/src/api/user_config.py b/apps/api/src/api/user_config.py index 99a8892..203acda 100644 --- a/apps/api/src/api/user_config.py +++ b/apps/api/src/api/user_config.py @@ -7,7 +7,7 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import _get_user, get_current_user_id, get_db_session -from src.models.user_config import UserConfig +from src.models import UserConfig logger = logging.getLogger(__name__) diff --git a/apps/api/src/api/workspace/__init__.py b/apps/api/src/api/workspace/__init__.py new file mode 100644 index 0000000..e2d8117 --- /dev/null +++ b/apps/api/src/api/workspace/__init__.py @@ -0,0 +1 @@ +"""Workspace module.""" diff --git a/apps/api/src/api/workspace_files.py b/apps/api/src/api/workspace_files.py index ab29e59..f43a2f8 100644 --- a/apps/api/src/api/workspace_files.py +++ b/apps/api/src/api/workspace_files.py @@ -6,7 +6,7 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.workspace import Workspace +from src.models import Workspace from src.services.file_service import FileService router = APIRouter(prefix="/workspaces/{workspace_id}/files") diff --git a/apps/api/src/api/workspace_git.py b/apps/api/src/api/workspace_git.py index 0a8177c..d5c8b91 100644 --- a/apps/api/src/api/workspace_git.py +++ b/apps/api/src/api/workspace_git.py @@ -6,7 +6,7 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.workspace import Workspace +from src.models import Workspace from src.services.git_operations import GitOperations router = APIRouter(prefix="/workspaces/{workspace_id}/git") diff --git a/apps/api/src/api/workspace_instances.py b/apps/api/src/api/workspace_instances.py index aaaea88..e865446 100644 --- a/apps/api/src/api/workspace_instances.py +++ b/apps/api/src/api/workspace_instances.py @@ -7,8 +7,8 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.tool_instance import ToolInstance -from src.models.workspace import Workspace +from src.models import ToolInstance +from src.models import Workspace router = APIRouter(prefix="/workspaces/{workspace_id}/instances") diff --git a/apps/api/src/api/workspaces.py b/apps/api/src/api/workspaces.py index acdee4d..4ce8938 100644 --- a/apps/api/src/api/workspaces.py +++ b/apps/api/src/api/workspaces.py @@ -9,9 +9,9 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from src.auth.dependencies import get_current_user_id, get_db_session -from src.models.git_repository import GitRepository -from src.models.tool_instance import ToolInstance -from src.models.workspace import Workspace +from src.models import GitRepository +from src.models import ToolInstance +from src.models import Workspace from src.services.workspace_manager import WorkspaceHasInstancesError, WorkspaceManager logger = logging.getLogger(__name__) diff --git a/apps/api/src/main.py b/apps/api/src/main.py index 17362f9..875025b 100644 --- a/apps/api/src/main.py +++ b/apps/api/src/main.py @@ -29,8 +29,8 @@ from src.api.workspace_git import router as workspace_git_router from src.api.workspace_instances import router as workspace_instances_router from src.api.workspaces import all_workspaces_router, router as workspaces_router from src.config import Settings -from src.models.notification import Notification # noqa: F401 – Alembic model discovery -from src.models.terminal_session import TerminalSessionModel # noqa: F401 – Alembic model discovery +from src.models import Notification # noqa: F401 – Alembic model discovery +from src.models import TerminalSessionModel # noqa: F401 – Alembic model discovery from src.database import init_database from src.logging_config import ( ExceptionLoggingMiddleware, diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index 49a69a4..e48f3fd 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -1,18 +1,18 @@ from src.models.base import Base -from src.models.config_profile import ConfigProfile, ConfigProfileInclude -from src.models.git_repository import GitRepository -from src.models.health_check import HealthCheck -from src.models.instance_event import InstanceEvent -from src.models.notification import Notification -from src.models.project import Project -from src.models.ssh_key import SSHKey -from src.models.terminal_session import TerminalSessionModel -from src.models.tool_definition_manifest import ToolDefinitionManifest -from src.models.tool_instance import ToolInstance -from src.models.tool_type import ToolType -from src.models.user import User -from src.models.user_config import UserConfig -from src.models.workspace import Workspace +from src.models.config.config_profile import ConfigProfile, ConfigProfileInclude +from src.models.project.git_repository import GitRepository +from src.models.project.project import Project +from src.models.project.workspace import Workspace +from src.models.system.health_check import HealthCheck +from src.models.system.instance_event import InstanceEvent +from src.models.system.notification import Notification +from src.models.system.terminal_session import TerminalSessionModel +from src.models.tool.tool_definition_manifest import ToolDefinitionManifest +from src.models.tool.tool_instance import ToolInstance +from src.models.tool.tool_type import ToolType +from src.models.user.ssh_key import SSHKey +from src.models.user.user import User +from src.models.user.user_config import UserConfig __all__ = [ "Base", diff --git a/apps/api/src/models/config/__init__.py b/apps/api/src/models/config/__init__.py new file mode 100644 index 0000000..ce43dbd --- /dev/null +++ b/apps/api/src/models/config/__init__.py @@ -0,0 +1,5 @@ +"""Config models module.""" + +from src.models.config.config_profile import ConfigProfile, ConfigProfileInclude + +__all__ = ["ConfigProfile", "ConfigProfileInclude"] diff --git a/apps/api/src/models/config_profile.py b/apps/api/src/models/config/config_profile.py similarity index 98% rename from apps/api/src/models/config_profile.py rename to apps/api/src/models/config/config_profile.py index 6853ef8..fa04bfa 100644 --- a/apps/api/src/models/config_profile.py +++ b/apps/api/src/models/config/config_profile.py @@ -17,7 +17,7 @@ from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin if TYPE_CHECKING: from src.models.project import Project - from src.models.tool_type import ToolType + from src.models import ToolType from src.models.user import User diff --git a/apps/api/src/models/project/__init__.py b/apps/api/src/models/project/__init__.py new file mode 100644 index 0000000..5c6b1da --- /dev/null +++ b/apps/api/src/models/project/__init__.py @@ -0,0 +1,7 @@ +"""Project models module.""" + +from src.models.project.git_repository import GitRepository +from src.models.project.project import Project +from src.models.project.workspace import Workspace + +__all__ = ["GitRepository", "Project", "Workspace"] diff --git a/apps/api/src/models/git_repository.py b/apps/api/src/models/project/git_repository.py similarity index 97% rename from apps/api/src/models/git_repository.py rename to apps/api/src/models/project/git_repository.py index d6f99fd..9afbc8e 100644 --- a/apps/api/src/models/git_repository.py +++ b/apps/api/src/models/project/git_repository.py @@ -10,7 +10,7 @@ from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin if TYPE_CHECKING: from src.models.project import Project - from src.models.ssh_key import SSHKey + from src.models import SSHKey from src.models.user import User diff --git a/apps/api/src/models/project.py b/apps/api/src/models/project/project.py similarity index 92% rename from apps/api/src/models/project.py rename to apps/api/src/models/project/project.py index 3e970f6..ca5ed24 100644 --- a/apps/api/src/models/project.py +++ b/apps/api/src/models/project/project.py @@ -8,8 +8,8 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin if TYPE_CHECKING: - from src.models.git_repository import GitRepository - from src.models.ssh_key import SSHKey + from src.models import GitRepository + from src.models import SSHKey from src.models.user import User diff --git a/apps/api/src/models/workspace.py b/apps/api/src/models/project/workspace.py similarity index 96% rename from apps/api/src/models/workspace.py rename to apps/api/src/models/project/workspace.py index 4cc9cf2..03bf61b 100644 --- a/apps/api/src/models/workspace.py +++ b/apps/api/src/models/project/workspace.py @@ -12,7 +12,7 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from src.models.base import Base, TimestampMixin if TYPE_CHECKING: - from src.models.git_repository import GitRepository + from src.models import GitRepository from src.models.user import User diff --git a/apps/api/src/models/system/__init__.py b/apps/api/src/models/system/__init__.py new file mode 100644 index 0000000..5949584 --- /dev/null +++ b/apps/api/src/models/system/__init__.py @@ -0,0 +1,8 @@ +"""System models module.""" + +from src.models.system.health_check import HealthCheck +from src.models.system.instance_event import InstanceEvent +from src.models.system.notification import Notification +from src.models.system.terminal_session import TerminalSessionModel + +__all__ = ["HealthCheck", "InstanceEvent", "Notification", "TerminalSessionModel"] diff --git a/apps/api/src/models/health_check.py b/apps/api/src/models/system/health_check.py similarity index 100% rename from apps/api/src/models/health_check.py rename to apps/api/src/models/system/health_check.py diff --git a/apps/api/src/models/instance_event.py b/apps/api/src/models/system/instance_event.py similarity index 100% rename from apps/api/src/models/instance_event.py rename to apps/api/src/models/system/instance_event.py diff --git a/apps/api/src/models/notification.py b/apps/api/src/models/system/notification.py similarity index 100% rename from apps/api/src/models/notification.py rename to apps/api/src/models/system/notification.py diff --git a/apps/api/src/models/terminal_session.py b/apps/api/src/models/system/terminal_session.py similarity index 100% rename from apps/api/src/models/terminal_session.py rename to apps/api/src/models/system/terminal_session.py diff --git a/apps/api/src/models/tool/__init__.py b/apps/api/src/models/tool/__init__.py new file mode 100644 index 0000000..f2e75fe --- /dev/null +++ b/apps/api/src/models/tool/__init__.py @@ -0,0 +1,7 @@ +"""Tool models module.""" + +from src.models.tool.tool_definition_manifest import ToolDefinitionManifest +from src.models.tool.tool_instance import ToolInstance +from src.models.tool.tool_type import ToolType + +__all__ = ["ToolDefinitionManifest", "ToolInstance", "ToolType"] diff --git a/apps/api/src/models/tool_definition_manifest.py b/apps/api/src/models/tool/tool_definition_manifest.py similarity index 100% rename from apps/api/src/models/tool_definition_manifest.py rename to apps/api/src/models/tool/tool_definition_manifest.py diff --git a/apps/api/src/models/tool_instance.py b/apps/api/src/models/tool/tool_instance.py similarity index 93% rename from apps/api/src/models/tool_instance.py rename to apps/api/src/models/tool/tool_instance.py index ddca249..772b267 100644 --- a/apps/api/src/models/tool_instance.py +++ b/apps/api/src/models/tool/tool_instance.py @@ -9,12 +9,12 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin if TYPE_CHECKING: - from src.models.config_profile import ConfigProfile - from src.models.git_repository import GitRepository + from src.models import ConfigProfile + from src.models import GitRepository from src.models.project import Project - from src.models.tool_type import ToolType + from src.models import ToolType from src.models.user import User - from src.models.workspace import Workspace + from src.models import Workspace class ToolInstance(UUIDPrimaryKeyMixin, TimestampMixin, Base): diff --git a/apps/api/src/models/tool_type.py b/apps/api/src/models/tool/tool_type.py similarity index 96% rename from apps/api/src/models/tool_type.py rename to apps/api/src/models/tool/tool_type.py index 1d7b6a3..aea5cb9 100644 --- a/apps/api/src/models/tool_type.py +++ b/apps/api/src/models/tool/tool_type.py @@ -6,8 +6,7 @@ from sqlalchemy import Uuid as UUID from sqlalchemy.orm import Mapped, mapped_column, relationship from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin - -from src.models.tool_definition_manifest import ToolDefinitionManifest +from src.models.tool.tool_definition_manifest import ToolDefinitionManifest if TYPE_CHECKING: from src.models.user import User diff --git a/apps/api/src/models/user/__init__.py b/apps/api/src/models/user/__init__.py new file mode 100644 index 0000000..2c29729 --- /dev/null +++ b/apps/api/src/models/user/__init__.py @@ -0,0 +1,7 @@ +"""User models module.""" + +from src.models.user.ssh_key import SSHKey +from src.models.user.user import User +from src.models.user.user_config import UserConfig + +__all__ = ["SSHKey", "User", "UserConfig"] diff --git a/apps/api/src/models/ssh_key.py b/apps/api/src/models/user/ssh_key.py similarity index 100% rename from apps/api/src/models/ssh_key.py rename to apps/api/src/models/user/ssh_key.py diff --git a/apps/api/src/models/user.py b/apps/api/src/models/user/user.py similarity index 90% rename from apps/api/src/models/user.py rename to apps/api/src/models/user/user.py index 91b83fd..b402546 100644 --- a/apps/api/src/models/user.py +++ b/apps/api/src/models/user/user.py @@ -7,8 +7,8 @@ from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin if TYPE_CHECKING: from src.models.project import Project - from src.models.ssh_key import SSHKey - from src.models.user_config import UserConfig + from src.models import SSHKey + from src.models import UserConfig class User(UUIDPrimaryKeyMixin, TimestampMixin, Base): diff --git a/apps/api/src/models/user_config.py b/apps/api/src/models/user/user_config.py similarity index 100% rename from apps/api/src/models/user_config.py rename to apps/api/src/models/user/user_config.py diff --git a/apps/api/src/schemas/config/__init__.py b/apps/api/src/schemas/config/__init__.py new file mode 100644 index 0000000..da7ff7c --- /dev/null +++ b/apps/api/src/schemas/config/__init__.py @@ -0,0 +1 @@ +"""Config module.""" diff --git a/apps/api/src/schemas/project/__init__.py b/apps/api/src/schemas/project/__init__.py new file mode 100644 index 0000000..1ed2378 --- /dev/null +++ b/apps/api/src/schemas/project/__init__.py @@ -0,0 +1 @@ +"""Project module.""" diff --git a/apps/api/src/schemas/system/__init__.py b/apps/api/src/schemas/system/__init__.py new file mode 100644 index 0000000..3f55c57 --- /dev/null +++ b/apps/api/src/schemas/system/__init__.py @@ -0,0 +1 @@ +"""System module.""" diff --git a/apps/api/src/schemas/tool/__init__.py b/apps/api/src/schemas/tool/__init__.py new file mode 100644 index 0000000..b05b87d --- /dev/null +++ b/apps/api/src/schemas/tool/__init__.py @@ -0,0 +1 @@ +"""Tool module.""" diff --git a/apps/api/src/schemas/user/__init__.py b/apps/api/src/schemas/user/__init__.py new file mode 100644 index 0000000..7f42956 --- /dev/null +++ b/apps/api/src/schemas/user/__init__.py @@ -0,0 +1 @@ +"""User module.""" diff --git a/apps/api/src/seeds/builtin_tool_types.py b/apps/api/src/seeds/builtin_tool_types.py index abf0f1d..1dacd52 100644 --- a/apps/api/src/seeds/builtin_tool_types.py +++ b/apps/api/src/seeds/builtin_tool_types.py @@ -5,7 +5,7 @@ import logging from sqlalchemy import select, text from src.database import SessionLocal -from src.models.tool_type import ToolType +from src.models import ToolType logger = logging.getLogger(__name__) diff --git a/apps/api/src/services/config/__init__.py b/apps/api/src/services/config/__init__.py new file mode 100644 index 0000000..da7ff7c --- /dev/null +++ b/apps/api/src/services/config/__init__.py @@ -0,0 +1 @@ +"""Config module.""" diff --git a/apps/api/src/services/config_profile_resolver.py b/apps/api/src/services/config_profile_resolver.py index cdb9e5c..471acb7 100644 --- a/apps/api/src/services/config_profile_resolver.py +++ b/apps/api/src/services/config_profile_resolver.py @@ -13,7 +13,7 @@ from typing import Any from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from src.models.config_profile import ConfigProfile, ConfigProfileInclude +from src.models import ConfigProfile, ConfigProfileInclude logger = logging.getLogger(__name__) diff --git a/apps/api/src/services/file_service.py b/apps/api/src/services/file_service.py index 072caa6..1f25eb8 100644 --- a/apps/api/src/services/file_service.py +++ b/apps/api/src/services/file_service.py @@ -4,7 +4,7 @@ import logging import os from dataclasses import dataclass -from src.models.workspace import Workspace +from src.models import Workspace logger = logging.getLogger(__name__) diff --git a/apps/api/src/services/git/__init__.py b/apps/api/src/services/git/__init__.py new file mode 100644 index 0000000..258e60f --- /dev/null +++ b/apps/api/src/services/git/__init__.py @@ -0,0 +1 @@ +"""Git module.""" diff --git a/apps/api/src/services/git_operations.py b/apps/api/src/services/git_operations.py index ecbd8d6..40a4536 100644 --- a/apps/api/src/services/git_operations.py +++ b/apps/api/src/services/git_operations.py @@ -4,7 +4,7 @@ import asyncio import logging from dataclasses import dataclass -from src.models.workspace import Workspace +from src.models import Workspace logger = logging.getLogger(__name__) diff --git a/apps/api/src/services/health_monitor.py b/apps/api/src/services/health_monitor.py index 187ee5f..bbabea4 100644 --- a/apps/api/src/services/health_monitor.py +++ b/apps/api/src/services/health_monitor.py @@ -10,8 +10,8 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.database import SessionLocal -from src.models.health_check import HealthCheck -from src.models.tool_instance import ToolInstance +from src.models import HealthCheck +from src.models import ToolInstance from src.services.correlation import get_correlation_id from src.services.docker import get_container_status from src.services.tunnel import check_tunnel_health diff --git a/apps/api/src/services/instance/__init__.py b/apps/api/src/services/instance/__init__.py new file mode 100644 index 0000000..0d47d65 --- /dev/null +++ b/apps/api/src/services/instance/__init__.py @@ -0,0 +1 @@ +"""Instance module.""" diff --git a/apps/api/src/services/lifecycle_hooks.py b/apps/api/src/services/lifecycle_hooks.py index 5af816e..f791366 100644 --- a/apps/api/src/services/lifecycle_hooks.py +++ b/apps/api/src/services/lifecycle_hooks.py @@ -6,8 +6,8 @@ from datetime import datetime, timezone from sqlalchemy.ext.asyncio import AsyncSession -from src.models.instance_event import InstanceEvent -from src.models.tool_instance import ToolInstance +from src.models import InstanceEvent +from src.models import ToolInstance from src.services.correlation import get_correlation_id from src.services.event_bus import InstanceEventBus, InstanceEventPayload from src.services.notification_service import notification_service diff --git a/apps/api/src/services/notification_service.py b/apps/api/src/services/notification_service.py index a6f4264..077dfff 100644 --- a/apps/api/src/services/notification_service.py +++ b/apps/api/src/services/notification_service.py @@ -8,7 +8,7 @@ from sqlalchemy import func, select, update from sqlalchemy.engine import CursorResult from sqlalchemy.ext.asyncio import AsyncSession -from src.models.notification import Notification +from src.models import Notification class NotificationService: diff --git a/apps/api/src/services/shared/__init__.py b/apps/api/src/services/shared/__init__.py new file mode 100644 index 0000000..3313f18 --- /dev/null +++ b/apps/api/src/services/shared/__init__.py @@ -0,0 +1 @@ +"""Shared module.""" diff --git a/apps/api/src/services/terminal/__init__.py b/apps/api/src/services/terminal/__init__.py new file mode 100644 index 0000000..f12436c --- /dev/null +++ b/apps/api/src/services/terminal/__init__.py @@ -0,0 +1 @@ +"""Terminal module.""" diff --git a/apps/api/src/services/terminal_manager.py b/apps/api/src/services/terminal_manager.py index b9605db..f37d9e9 100644 --- a/apps/api/src/services/terminal_manager.py +++ b/apps/api/src/services/terminal_manager.py @@ -9,7 +9,7 @@ from fastapi import WebSocket from sqlalchemy.dialects.postgresql import insert as pg_insert from src.database import SessionLocal -from src.models.terminal_session import TerminalSessionModel +from src.models import TerminalSessionModel from src.services.terminal_session import TerminalSession logger = logging.getLogger(__name__) diff --git a/apps/api/src/services/workspace_manager.py b/apps/api/src/services/workspace_manager.py index 98554a5..49ab6f8 100644 --- a/apps/api/src/services/workspace_manager.py +++ b/apps/api/src/services/workspace_manager.py @@ -14,15 +14,15 @@ from typing import TYPE_CHECKING from sqlalchemy import select -from src.models.workspace import Workspace +from src.models import Workspace from src.services.git_service import GitService from src.services.ssh_keys import _get_fernet if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession - from src.models.git_repository import GitRepository - from src.models.tool_instance import ToolInstance + from src.models import GitRepository + from src.models import ToolInstance logger = logging.getLogger(__name__) @@ -96,7 +96,7 @@ class WorkspaceManager: # Load SSH key if repo has one ssh_key = None if getattr(repo, "ssh_key_id", None) and session is not None: - from src.models.ssh_key import SSHKey + from src.models import SSHKey result = await session.execute( select(SSHKey).where(SSHKey.id == repo.ssh_key_id) @@ -181,8 +181,8 @@ class WorkspaceManager: # Load SSH key if repo has one ssh_key = None if session is not None: - from src.models.git_repository import GitRepository - from src.models.ssh_key import SSHKey + from src.models import GitRepository + from src.models import SSHKey repo = await session.get(GitRepository, workspace.repo_id) if repo and getattr(repo, "ssh_key_id", None): @@ -241,7 +241,7 @@ class WorkspaceManager: session: AsyncSession, ) -> list[ToolInstance]: """Get all tool instances associated with this workspace.""" - from src.models.tool_instance import ToolInstance + from src.models import ToolInstance result = await session.execute( select(ToolInstance).where(ToolInstance.workspace_id == workspace.id)