Compare commits
10 Commits
8816ee02ce
...
05a598812b
| Author | SHA1 | Date | |
|---|---|---|---|
| 05a598812b | |||
| 7515d9106f | |||
| 8c7affc933 | |||
| 2680a8c44a | |||
| 1021d61be3 | |||
| 7224afafd1 | |||
| 020f832eed | |||
| 7fe2790199 | |||
| 38c51ed95e | |||
| 37ccaa4fdc |
@@ -1,6 +1 @@
|
||||
from src.api.auth import router as auth_router
|
||||
from src.api.events import router as events_router
|
||||
from src.api.notifications import router as notifications_router
|
||||
from src.api.users import router as users_router
|
||||
|
||||
__all__ = ["auth_router", "events_router", "notifications_router", "users_router"]
|
||||
"""API routers package."""
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
"""Config module."""
|
||||
"""Config API routers module."""
|
||||
|
||||
from src.api.config.config_profiles import router as config_profiles_router
|
||||
from src.api.config.user_config import router as user_config_router
|
||||
|
||||
__all__ = ["config_profiles_router", "user_config_router"]
|
||||
|
||||
@@ -25,7 +25,7 @@ from src.schemas.config import (
|
||||
ValidateGitUrlRequest,
|
||||
ValidateGitUrlResponse,
|
||||
)
|
||||
from src.services.config_profile_resolver import (
|
||||
from src.services.config.config_profile_resolver import (
|
||||
ConfigProfileCycleError,
|
||||
check_include_cycle,
|
||||
resolve_profile,
|
||||
@@ -726,7 +726,7 @@ async def validate_git_url(
|
||||
key_path = None
|
||||
if data.ssh_key_id:
|
||||
from src.models import SSHKey
|
||||
from src.services.ssh_keys import _get_fernet
|
||||
from src.services.shared.ssh_keys import _get_fernet
|
||||
|
||||
try:
|
||||
ssh_key_uuid = uuid.UUID(data.ssh_key_id)
|
||||
@@ -1 +1,6 @@
|
||||
"""Project module."""
|
||||
"""Project API routers module."""
|
||||
|
||||
from src.api.project.git_repositories import router as git_repositories_router
|
||||
from src.api.project.projects import router as projects_router
|
||||
|
||||
__all__ = ["git_repositories_router", "projects_router"]
|
||||
|
||||
@@ -44,7 +44,7 @@ from src.utils.git_control import (
|
||||
)
|
||||
from src.utils.git_history import get_commit_detail, get_commit_history
|
||||
from src.utils.git_url_parser import parse_git_url
|
||||
from src.services.ssh_keys import _get_fernet
|
||||
from src.services.shared.ssh_keys import _get_fernet
|
||||
|
||||
router = APIRouter(prefix="/projects", tags=["git-repositories"])
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
"""System module."""
|
||||
"""System API routers module."""
|
||||
|
||||
from src.api.system.dashboard import router as dashboard_router
|
||||
from src.api.system.events import router as events_router
|
||||
from src.api.system.health import router as health_router
|
||||
from src.api.system.instance_proxy import router as instance_proxy_router
|
||||
from src.api.system.notifications import router as notifications_router
|
||||
from src.api.system.terminal import router as terminal_router
|
||||
|
||||
__all__ = [
|
||||
"dashboard_router",
|
||||
"events_router",
|
||||
"health_router",
|
||||
"instance_proxy_router",
|
||||
"notifications_router",
|
||||
"terminal_router",
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from src.auth.dependencies import get_current_user_id
|
||||
from src.services.event_bus import InstanceEventBus, InstanceEventPayload
|
||||
from src.services.instance.event_bus import InstanceEventBus, InstanceEventPayload
|
||||
|
||||
router = APIRouter(prefix="/events", tags=["events"])
|
||||
|
||||
@@ -10,7 +10,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 import UserConfig
|
||||
from src.services.notification_service import notification_service
|
||||
from src.services.shared.notification_service import notification_service
|
||||
|
||||
router = APIRouter(prefix="/notifications", tags=["notifications"])
|
||||
|
||||
@@ -15,7 +15,7 @@ from src.auth.dependencies import get_current_user_id, get_db_session
|
||||
from src.models import TerminalSessionModel
|
||||
from src.models import ToolInstance
|
||||
from src.models import ToolType
|
||||
from src.services.terminal_manager import MaxSessionsExceededError, terminal_manager
|
||||
from src.services.terminal.terminal_manager import MaxSessionsExceededError, terminal_manager
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -1 +1,13 @@
|
||||
"""Tool module."""
|
||||
"""Tool API routers module."""
|
||||
|
||||
from src.api.tool.sessions import sessions_router
|
||||
from src.api.tool.tool_definitions import router as tool_definitions_router
|
||||
from src.api.tool.tool_instances import router as tool_instances_router
|
||||
from src.api.tool.tool_types import router as tool_types_router
|
||||
|
||||
__all__ = [
|
||||
"sessions_router",
|
||||
"tool_definitions_router",
|
||||
"tool_instances_router",
|
||||
"tool_types_router",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
"""Sessions API endpoints (running instances for current user)."""
|
||||
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
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 import GitRepository
|
||||
from src.models import Project
|
||||
from src.models import ToolInstance
|
||||
from src.models import ToolType
|
||||
|
||||
sessions_router = APIRouter(prefix="/users", tags=["sessions"])
|
||||
|
||||
|
||||
@sessions_router.get(
|
||||
"/me/sessions",
|
||||
summary="Get user sessions",
|
||||
description="Get all active sessions (running instances) for the current user.",
|
||||
)
|
||||
async def get_user_sessions(
|
||||
user_id: uuid.UUID = Depends(get_current_user_id),
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
) -> dict:
|
||||
"""Get all active sessions for the current user.
|
||||
|
||||
Args:
|
||||
user_id: ID of the authenticated user.
|
||||
session: Database session.
|
||||
|
||||
Returns:
|
||||
Dictionary containing list of active sessions with instance details.
|
||||
"""
|
||||
_user = await _get_user(session, user_id)
|
||||
|
||||
result = await session.execute(
|
||||
select(ToolInstance)
|
||||
.where(ToolInstance.owner_id == user_id)
|
||||
.where(
|
||||
ToolInstance.status.in_(
|
||||
["running", "building", "pending", "stopped", "error"]
|
||||
)
|
||||
)
|
||||
.order_by(ToolInstance.created_at.desc())
|
||||
)
|
||||
instances = result.scalars().all()
|
||||
|
||||
sessions = []
|
||||
for instance in instances:
|
||||
tool_type = await session.get(ToolType, instance.tool_type_id)
|
||||
repo = await session.get(GitRepository, instance.repository_id)
|
||||
project = await session.get(Project, instance.project_id)
|
||||
|
||||
sessions.append(
|
||||
{
|
||||
"id": str(instance.id),
|
||||
"display_name": instance.display_name,
|
||||
"tool_type_name": tool_type.name if tool_type else "unknown",
|
||||
"tool_icon": tool_type.name if tool_type else "code",
|
||||
"tool_type_interfaces": [tool_type.interface_type] if tool_type else [],
|
||||
"repository_name": repo.name if repo else "unknown",
|
||||
"repository_id": str(instance.repository_id),
|
||||
"project_name": project.name if project else "unknown",
|
||||
"project_id": str(instance.project_id),
|
||||
"status": instance.status,
|
||||
"url": instance.url,
|
||||
"clone_mode": instance.clone_mode,
|
||||
"branch": instance.branch,
|
||||
"selected_config_profile_id": str(instance.selected_config_profile_id)
|
||||
if instance.selected_config_profile_id
|
||||
else None,
|
||||
"created_at": instance.created_at.isoformat()
|
||||
if instance.created_at
|
||||
else None,
|
||||
}
|
||||
)
|
||||
|
||||
return {"sessions": sessions}
|
||||
@@ -11,7 +11,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from src.auth.dependencies import get_current_user_id, get_db_session
|
||||
from src.models import ToolDefinitionManifest
|
||||
from src.models import ToolType
|
||||
from src.services.manifest_compiler import (
|
||||
from src.services.build.manifest_compiler import (
|
||||
compile_compose,
|
||||
compile_dockerfile,
|
||||
compile_entrypoint,
|
||||
@@ -173,7 +173,7 @@ async def list_tool_definitions(
|
||||
"""
|
||||
query = select(ToolDefinitionManifest)
|
||||
if not include_bases:
|
||||
query = query.where(ToolDefinitionManifest.is_base == False)
|
||||
query = query.where(ToolDefinitionManifest.is_base.is_(False))
|
||||
|
||||
result = await session.execute(
|
||||
query.order_by(ToolDefinitionManifest.created_at.desc())
|
||||
@@ -11,7 +11,6 @@ from datetime import datetime
|
||||
import httpx
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
APIRouter as FastAPIRouter,
|
||||
Depends,
|
||||
HTTPException,
|
||||
Request,
|
||||
@@ -27,16 +26,15 @@ from src.auth.dependencies import (
|
||||
get_current_user_id,
|
||||
get_db_session,
|
||||
)
|
||||
from src.services.event_bus import InstanceEventBus
|
||||
from src.services.lifecycle_hooks import publish_lifecycle_event
|
||||
from src.services.instance.event_bus import InstanceEventBus
|
||||
from src.services.instance.lifecycle_hooks import publish_lifecycle_event
|
||||
from src.models import ConfigProfile
|
||||
from src.models import GitRepository
|
||||
from src.models.project import Project
|
||||
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 (
|
||||
from src.services.git.clone import check_dirty_state, clone_repository
|
||||
from src.services.config.config_profile_resolver import (
|
||||
ConfigProfileCycleError,
|
||||
ResolvedProfile,
|
||||
apply_resolved_profile,
|
||||
@@ -61,14 +59,14 @@ from src.services.docker import (
|
||||
write_config_files,
|
||||
write_env_file,
|
||||
)
|
||||
from src.services.tunnel import (
|
||||
from src.services.shared.tunnel import (
|
||||
check_tunnel_health,
|
||||
recreate_tunnel,
|
||||
start_tunnel,
|
||||
stop_tunnel,
|
||||
)
|
||||
from src.services.docker_build import build_image
|
||||
from src.services.manifest_compiler import (
|
||||
from src.services.build.docker_build import build_image
|
||||
from src.services.build.manifest_compiler import (
|
||||
compile_compose,
|
||||
compile_dockerfile,
|
||||
compile_entrypoint,
|
||||
@@ -78,9 +76,12 @@ from src.services.manifest_compiler import (
|
||||
merge_with_config,
|
||||
resolve_base,
|
||||
)
|
||||
from src.services.permission_fixer import apply_mount_permissions, apply_ssh_permissions
|
||||
from src.services.readiness_probe import execute_probe
|
||||
from src.services.ssh_keys import cleanup_ssh_key_files, prepare_ssh_key_files
|
||||
from src.services.shared.permission_fixer import (
|
||||
apply_mount_permissions,
|
||||
apply_ssh_permissions,
|
||||
)
|
||||
from src.services.shared.readiness_probe import execute_probe
|
||||
from src.services.shared.ssh_keys import cleanup_ssh_key_files, prepare_ssh_key_files
|
||||
from src.schemas.tool import CreateInstanceRequest, StartInstanceRequest
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -1585,7 +1586,7 @@ async def start_instance(
|
||||
|
||||
# Mount selected SSH keys into container home dir
|
||||
if instance.ssh_key_ids:
|
||||
from src.services.ssh_keys import write_ssh_config, _sanitize_filename
|
||||
from src.services.shared.ssh_keys import write_ssh_config, _sanitize_filename
|
||||
|
||||
# Collect all valid keys first
|
||||
ssh_keys_to_mount = []
|
||||
@@ -2885,71 +2886,3 @@ async def proxy_to_instance(
|
||||
status_code=response.status_code,
|
||||
headers=response_headers,
|
||||
)
|
||||
|
||||
|
||||
sessions_router = FastAPIRouter(prefix="/users", tags=["sessions"])
|
||||
|
||||
|
||||
@sessions_router.get(
|
||||
"/me/sessions",
|
||||
summary="Get user sessions",
|
||||
description="Get all active sessions (running instances) for the current user.",
|
||||
)
|
||||
async def get_user_sessions(
|
||||
user_id: uuid.UUID = Depends(get_current_user_id),
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
) -> dict:
|
||||
"""Get all active sessions for the current user.
|
||||
|
||||
Args:
|
||||
user_id: ID of the authenticated user.
|
||||
session: Database session.
|
||||
|
||||
Returns:
|
||||
Dictionary containing list of active sessions with instance details.
|
||||
"""
|
||||
_user = await _get_user(session, user_id)
|
||||
|
||||
result = await session.execute(
|
||||
select(ToolInstance)
|
||||
.where(ToolInstance.owner_id == user_id)
|
||||
.where(
|
||||
ToolInstance.status.in_(
|
||||
["running", "building", "pending", "stopped", "error"]
|
||||
)
|
||||
)
|
||||
.order_by(ToolInstance.created_at.desc())
|
||||
)
|
||||
instances = result.scalars().all()
|
||||
|
||||
sessions = []
|
||||
for instance in instances:
|
||||
tool_type = await session.get(ToolType, instance.tool_type_id)
|
||||
repo = await session.get(GitRepository, instance.repository_id)
|
||||
project = await session.get(Project, instance.project_id)
|
||||
|
||||
sessions.append(
|
||||
{
|
||||
"id": str(instance.id),
|
||||
"display_name": instance.display_name,
|
||||
"tool_type_name": tool_type.name if tool_type else "unknown",
|
||||
"tool_icon": tool_type.name if tool_type else "code",
|
||||
"tool_type_interfaces": [tool_type.interface_type] if tool_type else [],
|
||||
"repository_name": repo.name if repo else "unknown",
|
||||
"repository_id": str(instance.repository_id),
|
||||
"project_name": project.name if project else "unknown",
|
||||
"project_id": str(instance.project_id),
|
||||
"status": instance.status,
|
||||
"url": instance.url,
|
||||
"clone_mode": instance.clone_mode,
|
||||
"branch": instance.branch,
|
||||
"selected_config_profile_id": str(instance.selected_config_profile_id)
|
||||
if instance.selected_config_profile_id
|
||||
else None,
|
||||
"created_at": instance.created_at.isoformat()
|
||||
if instance.created_at
|
||||
else None,
|
||||
}
|
||||
)
|
||||
|
||||
return {"sessions": sessions}
|
||||
@@ -4,7 +4,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.api.tool_types_validation import (
|
||||
from src.api.tool.tool_types_validation import (
|
||||
check_port_exposed,
|
||||
validate_compose_yaml,
|
||||
validate_required_variables,
|
||||
@@ -1 +1,7 @@
|
||||
"""User module."""
|
||||
"""User API routers module."""
|
||||
|
||||
from src.api.user.auth import router as auth_router
|
||||
from src.api.user.ssh_keys import router as ssh_keys_router
|
||||
from src.api.user.users import router as users_router
|
||||
|
||||
__all__ = ["auth_router", "ssh_keys_router", "users_router"]
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
"""Workspace module."""
|
||||
"""Workspace API routers module."""
|
||||
|
||||
from src.api.workspace.workspace_files import router as workspace_files_router
|
||||
from src.api.workspace.workspace_git import router as workspace_git_router
|
||||
from src.api.workspace.workspace_instances import router as workspace_instances_router
|
||||
from src.api.workspace.workspaces import (
|
||||
all_workspaces_router,
|
||||
router as workspaces_router,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"all_workspaces_router",
|
||||
"workspace_files_router",
|
||||
"workspace_git_router",
|
||||
"workspace_instances_router",
|
||||
"workspaces_router",
|
||||
]
|
||||
|
||||
@@ -7,7 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.auth.dependencies import get_current_user_id, get_db_session
|
||||
from src.models import Workspace
|
||||
from src.services.file_service import FileService
|
||||
from src.services.shared.file_service import FileService
|
||||
|
||||
router = APIRouter(prefix="/workspaces/{workspace_id}/files")
|
||||
|
||||
@@ -103,7 +103,7 @@ async def write_file(
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
if commit_message:
|
||||
from src.services.git_operations import GitOperations
|
||||
from src.services.git.git_operations import GitOperations
|
||||
|
||||
git = GitOperations(workspace)
|
||||
try:
|
||||
@@ -7,7 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.auth.dependencies import get_current_user_id, get_db_session
|
||||
from src.models import Workspace
|
||||
from src.services.git_operations import GitOperations
|
||||
from src.services.git.git_operations import GitOperations
|
||||
|
||||
router = APIRouter(prefix="/workspaces/{workspace_id}/git")
|
||||
|
||||
@@ -12,7 +12,7 @@ from src.auth.dependencies import get_current_user_id, get_db_session
|
||||
from src.models import GitRepository
|
||||
from src.models import ToolInstance
|
||||
from src.models import Workspace
|
||||
from src.services.workspace_manager import WorkspaceHasInstancesError, WorkspaceManager
|
||||
from src.services.shared.workspace_manager import WorkspaceHasInstancesError, WorkspaceManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -10,7 +10,7 @@ from collections.abc import Callable
|
||||
from fastapi import Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
from src.services.correlation import get_correlation_id
|
||||
from src.services.shared.correlation import get_correlation_id
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
+24
-21
@@ -7,27 +7,30 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from src.api.auth import router as auth_router
|
||||
from src.api.dashboard import router as dashboard_router
|
||||
from src.api.events import router as events_router
|
||||
from src.api.git_repositories import router as git_repositories_router
|
||||
from src.api.health import router as health_router
|
||||
from src.api.projects import router as projects_router
|
||||
from src.api.ssh_keys import router as ssh_keys_router
|
||||
from src.api.terminal import router as terminal_router
|
||||
from src.api.instance_proxy import router as instance_proxy_router
|
||||
from src.api.config_profiles import router as config_profiles_router
|
||||
from src.api.tool_definitions import router as tool_definitions_router
|
||||
from src.api.tool_instances import router as tool_instances_router
|
||||
from src.api.tool_instances import sessions_router
|
||||
from src.api.tool_types import router as tool_types_router
|
||||
from src.api.notifications import router as notifications_router
|
||||
from src.api.user_config import router as user_config_router
|
||||
from src.api.users import router as users_router
|
||||
from src.api.workspace_files import router as workspace_files_router
|
||||
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.api.config import config_profiles_router, user_config_router
|
||||
from src.api.project import git_repositories_router, projects_router
|
||||
from src.api.system import (
|
||||
dashboard_router,
|
||||
events_router,
|
||||
health_router,
|
||||
instance_proxy_router,
|
||||
notifications_router,
|
||||
terminal_router,
|
||||
)
|
||||
from src.api.tool import (
|
||||
sessions_router,
|
||||
tool_definitions_router,
|
||||
tool_instances_router,
|
||||
tool_types_router,
|
||||
)
|
||||
from src.api.user import auth_router, ssh_keys_router, users_router
|
||||
from src.api.workspace import (
|
||||
all_workspaces_router,
|
||||
workspace_files_router,
|
||||
workspace_git_router,
|
||||
workspace_instances_router,
|
||||
workspaces_router,
|
||||
)
|
||||
from src.config import Settings
|
||||
from src.models import Notification # noqa: F401 – Alembic model discovery
|
||||
from src.models import TerminalSessionModel # noqa: F401 – Alembic model discovery
|
||||
|
||||
@@ -6,7 +6,7 @@ from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, field_validator, model_validator
|
||||
|
||||
from src.api.tool_types_validation import (
|
||||
from src.api.tool.tool_types_validation import (
|
||||
check_port_exposed,
|
||||
validate_compose_yaml,
|
||||
validate_required_variables,
|
||||
|
||||
@@ -1 +1,25 @@
|
||||
"""Config module."""
|
||||
"""Config profile services module."""
|
||||
|
||||
from src.services.config.config_profile_resolver import (
|
||||
ConfigProfileCycleError,
|
||||
ConfigProfileNotFoundError,
|
||||
ResolvedMount,
|
||||
ResolvedProfile,
|
||||
apply_resolved_profile,
|
||||
check_include_cycle,
|
||||
expand_container_path,
|
||||
resolve_profile,
|
||||
resolved_profile_to_dict,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"ConfigProfileCycleError",
|
||||
"ConfigProfileNotFoundError",
|
||||
"ResolvedMount",
|
||||
"ResolvedProfile",
|
||||
"apply_resolved_profile",
|
||||
"check_include_cycle",
|
||||
"expand_container_path",
|
||||
"resolve_profile",
|
||||
"resolved_profile_to_dict",
|
||||
]
|
||||
|
||||
@@ -1 +1,19 @@
|
||||
"""Git module."""
|
||||
"""Git services module."""
|
||||
|
||||
from src.services.git.clone import (
|
||||
check_dirty_state,
|
||||
clone_repository,
|
||||
remove_clone_directory,
|
||||
)
|
||||
from src.services.git.git_operations import Commit, GitOperations, GitStatus
|
||||
from src.services.git.git_service import GitService
|
||||
|
||||
__all__ = [
|
||||
"check_dirty_state",
|
||||
"clone_repository",
|
||||
"remove_clone_directory",
|
||||
"Commit",
|
||||
"GitOperations",
|
||||
"GitStatus",
|
||||
"GitService",
|
||||
]
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
"""Instance module."""
|
||||
"""Instance lifecycle services module."""
|
||||
|
||||
from src.services.instance.event_bus import InstanceEventBus
|
||||
from src.services.instance.health_monitor import HealthMonitor
|
||||
from src.services.instance.lifecycle_hooks import publish_lifecycle_event
|
||||
|
||||
__all__ = ["InstanceEventBus", "HealthMonitor", "publish_lifecycle_event"]
|
||||
|
||||
+4
-4
@@ -12,11 +12,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from src.database import SessionLocal
|
||||
from src.models import HealthCheck
|
||||
from src.models import ToolInstance
|
||||
from src.services.correlation import get_correlation_id
|
||||
from src.services.shared.correlation import get_correlation_id
|
||||
from src.services.docker import get_container_status
|
||||
from src.services.tunnel import check_tunnel_health
|
||||
from src.services.event_bus import InstanceEventBus, InstanceEventPayload
|
||||
from src.services.notification_service import notification_service
|
||||
from src.services.shared.tunnel import check_tunnel_health
|
||||
from src.services.instance.event_bus import InstanceEventBus, InstanceEventPayload
|
||||
from src.services.shared.notification_service import notification_service
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
+3
-3
@@ -8,9 +8,9 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
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
|
||||
from src.services.shared.correlation import get_correlation_id
|
||||
from src.services.instance.event_bus import InstanceEventBus, InstanceEventPayload
|
||||
from src.services.shared.notification_service import notification_service
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -1 +1,51 @@
|
||||
"""Shared module."""
|
||||
"""Shared services module."""
|
||||
|
||||
from src.services.shared.correlation import CorrelationIdMiddleware, get_correlation_id
|
||||
from src.services.shared.file_service import FileEntry, FileService
|
||||
from src.services.shared.notification_service import NotificationService
|
||||
from src.services.shared.permission_fixer import (
|
||||
PermissionFixError,
|
||||
apply_mount_permissions,
|
||||
apply_ssh_permissions,
|
||||
check_root_user_available,
|
||||
)
|
||||
from src.services.shared.readiness_probe import execute_probe
|
||||
from src.services.shared.ssh_keys import (
|
||||
cleanup_ssh_key_files,
|
||||
prepare_ssh_key_files,
|
||||
write_ssh_config,
|
||||
)
|
||||
from src.services.shared.tunnel import (
|
||||
check_tunnel_health,
|
||||
recreate_tunnel,
|
||||
start_tunnel,
|
||||
stop_tunnel,
|
||||
)
|
||||
from src.services.shared.workspace_manager import (
|
||||
SyncResult,
|
||||
WorkspaceHasInstancesError,
|
||||
WorkspaceManager,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"CorrelationIdMiddleware",
|
||||
"FileEntry",
|
||||
"FileService",
|
||||
"NotificationService",
|
||||
"PermissionFixError",
|
||||
"SyncResult",
|
||||
"WorkspaceHasInstancesError",
|
||||
"WorkspaceManager",
|
||||
"apply_mount_permissions",
|
||||
"apply_ssh_permissions",
|
||||
"check_root_user_available",
|
||||
"check_tunnel_health",
|
||||
"cleanup_ssh_key_files",
|
||||
"execute_probe",
|
||||
"get_correlation_id",
|
||||
"prepare_ssh_key_files",
|
||||
"recreate_tunnel",
|
||||
"start_tunnel",
|
||||
"stop_tunnel",
|
||||
"write_ssh_config",
|
||||
]
|
||||
|
||||
+2
-2
@@ -15,8 +15,8 @@ from typing import TYPE_CHECKING
|
||||
from sqlalchemy import select
|
||||
|
||||
from src.models import Workspace
|
||||
from src.services.git_service import GitService
|
||||
from src.services.ssh_keys import _get_fernet
|
||||
from src.services.git.git_service import GitService
|
||||
from src.services.shared.ssh_keys import _get_fernet
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -1 +1,9 @@
|
||||
"""Terminal module."""
|
||||
"""Terminal services module."""
|
||||
|
||||
from src.services.terminal.terminal_manager import (
|
||||
MaxSessionsExceededError,
|
||||
TerminalManager,
|
||||
)
|
||||
from src.services.terminal.terminal_session import TerminalSession
|
||||
|
||||
__all__ = ["MaxSessionsExceededError", "TerminalManager", "TerminalSession"]
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||
|
||||
from src.database import SessionLocal
|
||||
from src.models import TerminalSessionModel
|
||||
from src.services.terminal_session import TerminalSession
|
||||
from src.services.terminal.terminal_session import TerminalSession
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
listToolTypes,
|
||||
updateToolType,
|
||||
validateToolType,
|
||||
} from "../api/tool_types";
|
||||
} from "../api/tool-types";
|
||||
|
||||
const mockGet = vi.fn();
|
||||
const mockPost = vi.fn();
|
||||
@@ -10,11 +10,11 @@ import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
||||
import { EventProvider } from "../state/events";
|
||||
import { ToastProvider } from "../state/toast";
|
||||
import { NotificationProvider } from "../state/notifications";
|
||||
import { EventToastBridge } from "./event-toast-bridge";
|
||||
import { NotificationCenter } from "./notification-center";
|
||||
import { EventToastBridge } from "./features/notification/event-toast-bridge";
|
||||
import { NotificationCenter } from "./features/notification/notification-center";
|
||||
import { Icon } from "./icon";
|
||||
import { MobileNav } from "./mobile-nav";
|
||||
import { StartToolFAB } from "./start-tool-fab";
|
||||
import { MobileNav } from "./features/mobile/mobile-nav";
|
||||
import { StartToolFAB } from "./features/tool/start-tool-fab";
|
||||
import type { IconName } from "../utils/icons";
|
||||
|
||||
const NAV_ITEMS: {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface CommitDialogProps {
|
||||
isOpen: boolean;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { commitChanges } from "../api/git_repositories";
|
||||
import { commitChanges } from "../../../api/git-repositories";
|
||||
|
||||
interface CommitPanelProps {
|
||||
projectId: string;
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { apiClient } from "../api/client";
|
||||
import { useAuth } from "../state/auth";
|
||||
import { CodeEditor } from "../components/code-editor";
|
||||
import { CommitDialog } from "../components/commit-dialog";
|
||||
import { Icon } from "../components/icon";
|
||||
import { SyntaxHighlighter } from "../components/syntax-highlighter";
|
||||
import { detectLanguage } from "../utils/language";
|
||||
import { apiClient } from "../../../api/client";
|
||||
import { useAuth } from "../../../state/auth";
|
||||
import { CodeEditor } from "../../code-editor";
|
||||
import { CommitDialog } from "./commit-dialog";
|
||||
import { Icon } from "../../icon";
|
||||
import { SyntaxHighlighter } from "../../syntax-highlighter";
|
||||
import { detectLanguage } from "../../../utils/language";
|
||||
|
||||
interface FileEditorProps {
|
||||
projectId: string;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { validateGitUrl } from "../api/config_profiles";
|
||||
import type { GitMount, GitMountMapping } from "../api/config_profiles";
|
||||
import { Icon } from "../../icon";
|
||||
import { validateGitUrl } from "../../../api/config_profiles";
|
||||
import type { GitMount, GitMountMapping } from "../../../api/config_profiles";
|
||||
|
||||
interface GitMountEditorProps {
|
||||
mounts: GitMount[];
|
||||
+2
-2
@@ -8,8 +8,8 @@ import {
|
||||
pullRepository,
|
||||
pushRepository,
|
||||
type GitStatus,
|
||||
} from "../api/git_repositories";
|
||||
import { Icon } from "./icon";
|
||||
} from "../../../api/git-repositories";
|
||||
import { Icon } from "../../icon";
|
||||
import { MergeDialog } from "./merge-dialog";
|
||||
|
||||
interface GitToolbarProps {
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { mergeBranches } from "../api/git_repositories";
|
||||
import { Icon } from "./icon";
|
||||
import { mergeBranches } from "../../../api/git-repositories";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface MergeDialogProps {
|
||||
projectId: string;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import type { IconName } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
import type { IconName } from "../../icon";
|
||||
|
||||
export interface MobileActionSheetItem {
|
||||
id: string;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface Field {
|
||||
label: string;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface MobileFABProps {
|
||||
onClick: () => void;
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { Icon } from "./icon";
|
||||
import type { IconName } from "../utils/icons";
|
||||
import { Icon } from "../../icon";
|
||||
import type { IconName } from "../../../utils/icons";
|
||||
|
||||
interface MobileListItem {
|
||||
id: string;
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { useState } from "react";
|
||||
import { NavLink, useLocation } from "react-router-dom";
|
||||
import { Icon } from "./icon";
|
||||
import { ToolsBottomSheet } from "./tools-bottom-sheet";
|
||||
import type { IconName } from "../utils/icons";
|
||||
import { Icon } from "../../icon";
|
||||
import { ToolsBottomSheet } from "../tool/tools-bottom-sheet";
|
||||
import type { IconName } from "../../../utils/icons";
|
||||
|
||||
interface MobileNavProps {
|
||||
sessionCount?: number;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
||||
import { Icon } from "./icon";
|
||||
import { useMobileViewport } from "../../../hooks/use-mobile-viewport";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface MobilePageHeaderProps {
|
||||
title: string;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface MobileTerminalHeaderProps {
|
||||
instanceName?: string;
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
import React, { useState, useCallback } from "react";
|
||||
import { TerminalComponent } from "./terminal";
|
||||
import { TerminalComponent } from "../terminal/terminal";
|
||||
import { MobileTerminalHeader } from "./mobile-terminal-header";
|
||||
import { SpecialKeysStrip } from "./special-keys-strip";
|
||||
import { SpecialKeysPanel } from "./special-keys-panel";
|
||||
import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
||||
import { useVirtualKeyboard } from "../hooks/use-virtual-keyboard";
|
||||
import { useAutoHide } from "../hooks/use-auto-hide";
|
||||
import type { ModifierKey } from "../hooks/use-special-keys";
|
||||
import { SpecialKeysStrip } from "../terminal/special-keys-strip";
|
||||
import { SpecialKeysPanel } from "../terminal/special-keys-panel";
|
||||
import { useMobileViewport } from "../../../hooks/use-mobile-viewport";
|
||||
import { useVirtualKeyboard } from "../../../hooks/use-virtual-keyboard";
|
||||
import { useAutoHide } from "../../../hooks/use-auto-hide";
|
||||
import type { ModifierKey } from "../../../hooks/use-special-keys";
|
||||
|
||||
interface MobileTerminalWrapperProps {
|
||||
instanceId: string;
|
||||
+3
-3
@@ -2,15 +2,15 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { render, act } from "@testing-library/react";
|
||||
import { EventToastBridge } from "./event-toast-bridge";
|
||||
import { useEventContext } from "../state/events";
|
||||
import { getUserConfig } from "../api/settings";
|
||||
import { getUserConfig } from "../../../api/settings";
|
||||
import { handleEventToast } from "./toast-rules";
|
||||
import type { InstanceEventPayload } from "../types/events";
|
||||
import type { InstanceEventPayload } from "../../../types/events";
|
||||
|
||||
vi.mock("../state/events", () => ({
|
||||
useEventContext: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../api/settings", () => ({
|
||||
vi.mock("../../../api/settings", () => ({
|
||||
getUserConfig: vi.fn(),
|
||||
}));
|
||||
|
||||
+4
-4
@@ -1,12 +1,12 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEventContext } from "../state/events";
|
||||
import { useEventContext } from "../../../state/events";
|
||||
import {
|
||||
handleEventToast,
|
||||
mapEventToCategory,
|
||||
mapEventToSeverity,
|
||||
} from "./toast-rules";
|
||||
import { getUserConfig } from "../api/settings";
|
||||
import type { UserConfig } from "../api/settings";
|
||||
} from "../../toast-rules";
|
||||
import { getUserConfig } from "../../../api/settings";
|
||||
import type { UserConfig } from "../../../api/settings";
|
||||
|
||||
interface ToastConfig {
|
||||
notification_toast_level: string;
|
||||
+4
-4
@@ -3,7 +3,7 @@ import { render, screen, fireEvent, cleanup } from "@testing-library/react";
|
||||
import { NotificationCenter } from "./notification-center";
|
||||
import { NotificationProvider } from "../state/notifications";
|
||||
|
||||
vi.mock("../api/notifications", () => ({
|
||||
vi.mock("../../../api/notifications", () => ({
|
||||
getNotifications: vi.fn(),
|
||||
getUnreadCount: vi.fn(),
|
||||
markNotificationRead: vi.fn(),
|
||||
@@ -12,7 +12,7 @@ vi.mock("../api/notifications", () => ({
|
||||
clearAllNotifications: vi.fn(),
|
||||
}));
|
||||
|
||||
import { getNotifications, getUnreadCount } from "../api/notifications";
|
||||
import { getNotifications, getUnreadCount } from "../../../api/notifications";
|
||||
|
||||
const mockedGetNotifications = vi.mocked(getNotifications);
|
||||
const mockedGetUnreadCount = vi.mocked(getUnreadCount);
|
||||
@@ -142,7 +142,7 @@ describe("NotificationCenter", () => {
|
||||
fireEvent.click(screen.getByRole("button", { name: /mark all as read/i }));
|
||||
|
||||
const { markAllNotificationsRead: mockMarkAll } = await import(
|
||||
"../api/notifications"
|
||||
"../../../api/notifications"
|
||||
);
|
||||
expect(vi.mocked(mockMarkAll)).toHaveBeenCalled();
|
||||
});
|
||||
@@ -162,7 +162,7 @@ describe("NotificationCenter", () => {
|
||||
fireEvent.click(screen.getByRole("button", { name: /clear all/i }));
|
||||
|
||||
const { clearAllNotifications: mockClearAll } = await import(
|
||||
"../api/notifications"
|
||||
"../../../api/notifications"
|
||||
);
|
||||
expect(vi.mocked(mockClearAll)).toHaveBeenCalled();
|
||||
});
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useNotifications } from "../hooks/use-notifications";
|
||||
import { useNotifications } from "../../../hooks/use-notifications";
|
||||
import { NotificationItem } from "./notification-item";
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface NotificationCenterProps {
|
||||
isMobileTerminal?: boolean;
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
import { Icon } from "./icon";
|
||||
import { formatRelativeTime } from "../utils/time";
|
||||
import type { NotificationItem as NotificationItemType } from "../api/notifications";
|
||||
import { Icon } from "../../icon";
|
||||
import { formatRelativeTime } from "../../../utils/time";
|
||||
import type { NotificationItem as NotificationItemType } from "../../../api/notifications";
|
||||
|
||||
export interface NotificationItemProps {
|
||||
notification: NotificationItemType;
|
||||
@@ -8,7 +8,7 @@ export interface NotificationItemProps {
|
||||
onDismiss: (id: string) => void;
|
||||
}
|
||||
|
||||
import type { IconName } from "../utils/icons";
|
||||
import type { IconName } from "../../../utils/icons";
|
||||
|
||||
const severityIconMap: Record<string, IconName> = {
|
||||
info: "info",
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/re
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { RepositoriesSettingsTab } from "./repositories-settings-tab";
|
||||
import * as gitRepositoriesApi from "../api/git_repositories";
|
||||
import * as gitRepositoriesApi from "../../../api/git-repositories";
|
||||
|
||||
const mockRepositories = [
|
||||
{
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { deleteRepository, listRepositories, type GitRepository } from "../api/git_repositories";
|
||||
import { deleteRepository, listRepositories, type GitRepository } from "../../../api/git-repositories";
|
||||
import { RepositoryCreateDialog } from "./repository-create-dialog";
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
export const RepositoriesSettingsTab: React.FC = () => {
|
||||
const { projectId } = useParams<{ projectId: string }>();
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import { createRepository, parseGitUrl, type GitRepositoryCreate, type URLParseResult } from "../api/git_repositories";
|
||||
import { listSSHKeys, type SSHKey } from "../api/ssh_keys";
|
||||
import { Icon } from "./icon";
|
||||
import { createRepository, parseGitUrl, type GitRepositoryCreate, type URLParseResult } from "../../../api/git-repositories";
|
||||
import { listSSHKeys, type SSHKey } from "../../../api/ssh-keys";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
type CreateMode = "clone" | "blank";
|
||||
type UrlValidationStatus = "idle" | "validating" | "valid" | "needs-parsing" | "invalid";
|
||||
+7
-7
@@ -1,11 +1,11 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { createInstance, startInstance, type ToolInstance } from "../api/sessions";
|
||||
import type { Project } from "../types";
|
||||
import { listRepositoryBranches, type GitRepository, type Branch } from "../api/git_repositories";
|
||||
import type { ToolType } from "../api/tool_types";
|
||||
import { listSSHKeys, type SSHKey } from "../api/ssh_keys";
|
||||
import { listConfigProfiles, type ConfigProfile } from "../api/config_profiles";
|
||||
import { Icon } from "../../icon";
|
||||
import { createInstance, startInstance, type ToolInstance } from "../../../api/sessions";
|
||||
import type { Project } from "../../../types";
|
||||
import { listRepositoryBranches, type GitRepository, type Branch } from "../../../api/git-repositories";
|
||||
import type { ToolType } from "../../../api/tool-types";
|
||||
import { listSSHKeys, type SSHKey } from "../../../api/ssh-keys";
|
||||
import { listConfigProfiles, type ConfigProfile } from "../../../api/config_profiles";
|
||||
|
||||
interface CreateSessionFormProps {
|
||||
projects: Project[];
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import type { Session } from "../api/sessions";
|
||||
import { Icon } from "./icon";
|
||||
import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
||||
import { MobileActionSheet } from "./mobile-action-sheet";
|
||||
import type { IconName } from "./icon";
|
||||
import type { Session } from "../../../api/sessions";
|
||||
import { Icon } from "../../icon";
|
||||
import { useMobileViewport } from "../../../hooks/use-mobile-viewport";
|
||||
import { MobileActionSheet } from "../mobile/mobile-action-sheet";
|
||||
import type { IconName } from "../../icon";
|
||||
|
||||
export interface SessionCardProps {
|
||||
session: Session;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import type { Session } from "../api/sessions";
|
||||
import type { Session } from "../../../api/sessions";
|
||||
import { SessionCard } from "./session-card";
|
||||
import type { InstanceHealth } from "../api/sessions";
|
||||
import type { InstanceHealth } from "../../../api/sessions";
|
||||
|
||||
export interface SessionListProps {
|
||||
sessions: Session[];
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { getSequenceWithModifier, type SpecialKey, type ModifierKey } from "../hooks/use-special-keys";
|
||||
import { getSequenceWithModifier, type SpecialKey, type ModifierKey } from "../../../hooks/use-special-keys";
|
||||
|
||||
interface SpecialKeysPanelProps {
|
||||
onSend: (data: string) => void;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { getSequenceWithModifier, type SpecialKey, type ModifierKey } from "../hooks/use-special-keys";
|
||||
import { getSequenceWithModifier, type SpecialKey, type ModifierKey } from "../../../hooks/use-special-keys";
|
||||
|
||||
interface SpecialKeysStripProps {
|
||||
onSend: (data: string) => void;
|
||||
+1
-1
@@ -14,7 +14,7 @@ import "xterm/css/xterm.css";
|
||||
import {
|
||||
applyModifierToChar,
|
||||
type ModifierKey,
|
||||
} from "../hooks/use-special-keys";
|
||||
} from "../../../hooks/use-special-keys";
|
||||
|
||||
export interface TerminalProps {
|
||||
instanceId: string;
|
||||
+8
-8
@@ -1,19 +1,19 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Icon } from "./icon";
|
||||
import type { ToolInstance } from "../api/sessions";
|
||||
import { Icon } from "../../icon";
|
||||
import type { ToolInstance } from "../../../api/sessions";
|
||||
import {
|
||||
deleteInstance,
|
||||
listInstances,
|
||||
restartInstance,
|
||||
startInstance,
|
||||
stopInstance,
|
||||
} from "../api/sessions";
|
||||
import type { ToolType } from "../api/tool_types";
|
||||
import { CreateSessionForm } from "./create-session-form";
|
||||
import { listConfigProfiles, type ConfigProfile } from "../api/config_profiles";
|
||||
import { listSSHKeys, type SSHKey } from "../api/ssh_keys";
|
||||
import { useEventContext } from "../state/events";
|
||||
} from "../../../api/sessions";
|
||||
import type { ToolType } from "../../../api/tool-types";
|
||||
import { CreateSessionForm } from "../session/create-session-form";
|
||||
import { listConfigProfiles, type ConfigProfile } from "../../../api/config_profiles";
|
||||
import { listSSHKeys, type SSHKey } from "../../../api/ssh-keys";
|
||||
import { useEventContext } from "../../../state/events";
|
||||
|
||||
const API_BASE_URL =
|
||||
import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000";
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { extractErrorMessage } from "../utils/errors";
|
||||
import { Icon } from "../../icon";
|
||||
import { extractErrorMessage } from "../../../utils/errors";
|
||||
import {
|
||||
compileToolDefinition,
|
||||
type ToolDefinitionManifest,
|
||||
} from "../api/tool_definitions";
|
||||
} from "../../../api/tool_definitions";
|
||||
|
||||
interface PackageEntry {
|
||||
name: string;
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
/** Floating action button to start a tool from any page. */
|
||||
|
||||
import { useState } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
import { ToolStarter } from "./tool-starter";
|
||||
import type { Workspace } from "../types/workspace";
|
||||
import { listAllWorkspaces } from "../api/workspaces";
|
||||
import type { Workspace } from "../../../types/workspace";
|
||||
import { listAllWorkspaces } from "../../../api/workspaces";
|
||||
|
||||
export function StartToolFAB() {
|
||||
const [open, setOpen] = useState(false);
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
/** Modal for starting a tool on a workspace. */
|
||||
|
||||
import { useState } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { listToolTypes, type ToolType } from "../api/tool_types";
|
||||
import { useAsyncData } from "../hooks/use-async-data";
|
||||
import type { Workspace } from "../types/workspace";
|
||||
import { Icon } from "../../icon";
|
||||
import { listToolTypes, type ToolType } from "../../../api/tool-types";
|
||||
import { useAsyncData } from "../../../hooks/use-async-data";
|
||||
import type { Workspace } from "../../../types/workspace";
|
||||
|
||||
export interface StartToolModalProps {
|
||||
workspace: Workspace;
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
/** Unified tool starter — workspace-first, fetches real tool types and config profiles. */
|
||||
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { Icon } from "./icon";
|
||||
import { listToolTypes, type ToolType } from "../api/tool_types";
|
||||
import { listConfigProfiles, type ConfigProfile } from "../api/config_profiles";
|
||||
import { listSSHKeys, type SSHKey } from "../api/ssh_keys";
|
||||
import type { Workspace } from "../types/workspace";
|
||||
import type { ToolInstance } from "../api/sessions";
|
||||
import { Icon } from "../../icon";
|
||||
import { listToolTypes, type ToolType } from "../../../api/tool-types";
|
||||
import { listConfigProfiles, type ConfigProfile } from "../../../api/config_profiles";
|
||||
import { listSSHKeys, type SSHKey } from "../../../api/ssh-keys";
|
||||
import type { Workspace } from "../../../types/workspace";
|
||||
import type { ToolInstance } from "../../../api/sessions";
|
||||
|
||||
export interface ToolStarterProps {
|
||||
workspace: Workspace;
|
||||
@@ -114,7 +114,7 @@ export function ToolStarter({
|
||||
setStarting(true);
|
||||
setError(null);
|
||||
try {
|
||||
const { createInstance, startInstance } = await import("../api/sessions");
|
||||
const { createInstance, startInstance } = await import("../../../api/sessions");
|
||||
const instance = await createInstance(
|
||||
workspace.project_id,
|
||||
workspace.repo_id,
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { Icon } from "./icon";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
interface ToolsBottomSheetProps {
|
||||
isOpen: boolean;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user