feat: multi-session terminal backend core (PR 1)
- Add TerminalSessionModel DB table with instance_id FK, name, status, created_at, last_activity_at, closed_at columns - Add Alembic migration for terminal_sessions table - Refactor TerminalManager to use composite key (instance_id, session_id) supporting up to 5 concurrent sessions per instance - Add create_session, get_session, get_sessions_for_instance, close_session - Preserve get_or_create_session for backward compatibility (default session) - Fix attach_websocket to only close sockets within same session - Add name (auto-generated 'Session N') and status tracking to TerminalSession - Add 7 unit tests for multi-session logic Quality gates: pytest (7 new passed, 174 total passed, 51 pre-existing failures)
This commit is contained in:
@@ -4,9 +4,23 @@ from src.models.config_profile import ConfigProfile, ConfigProfileInclude
|
||||
from src.models.git_repository import GitRepository
|
||||
from src.models.project import Project
|
||||
from src.models.ssh_key import SSHKey
|
||||
from src.models.terminal_session import TerminalSessionModel
|
||||
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
|
||||
|
||||
__all__ = ["Base", "ConfigFolder", "ConfigProfile", "ConfigProfileInclude", "GitRepository", "Project", "SSHKey", "ToolInstance", "ToolType", "User", "UserConfig"]
|
||||
__all__ = [
|
||||
"Base",
|
||||
"ConfigFolder",
|
||||
"ConfigProfile",
|
||||
"ConfigProfileInclude",
|
||||
"GitRepository",
|
||||
"Project",
|
||||
"SSHKey",
|
||||
"TerminalSessionModel",
|
||||
"ToolInstance",
|
||||
"ToolType",
|
||||
"User",
|
||||
"UserConfig",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
"""Terminal session database model."""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import DateTime, ForeignKey, String
|
||||
from sqlalchemy import Uuid as UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin
|
||||
|
||||
|
||||
class TerminalSessionModel(UUIDPrimaryKeyMixin, TimestampMixin, Base):
|
||||
"""Database model for terminal session metadata."""
|
||||
|
||||
__tablename__ = "terminal_sessions"
|
||||
|
||||
instance_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(),
|
||||
ForeignKey("tool_instances.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(50),
|
||||
nullable=False,
|
||||
default="active",
|
||||
)
|
||||
last_activity_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=True,
|
||||
)
|
||||
closed_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=True,
|
||||
)
|
||||
Reference in New Issue
Block a user