feat: Implement web-based terminal with session management, command history, and dedicated UI.
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled

This commit is contained in:
2026-03-03 11:51:57 -05:00
parent 88742892d0
commit d29eefcef4
12 changed files with 638 additions and 189 deletions
+5 -1
View File
@@ -201,6 +201,7 @@ class TerminalCommandLogRepository:
TerminalCommandLog.command_hash,
func.max(TerminalCommandLog.created_at).label("max_created"),
func.count(TerminalCommandLog.id).label("execution_count"),
func.max(TerminalCommandLog.is_pinned).label("is_pinned"),
)
.where(and_(*conditions))
.group_by(TerminalCommandLog.command_hash)
@@ -214,13 +215,15 @@ class TerminalCommandLogRepository:
TerminalCommandLog.command_hash,
subq.c.max_created,
subq.c.execution_count,
subq.c.is_pinned,
)
.join(subq, and_(
TerminalCommandLog.command_hash == subq.c.command_hash,
TerminalCommandLog.created_at == subq.c.max_created,
))
.where(TerminalCommandLog.host_id == host_id)
.order_by(subq.c.max_created.desc())
# Sort by pinned status first (pinned at top), then by max_created
.order_by(subq.c.is_pinned.desc(), subq.c.max_created.desc())
.limit(limit)
)
@@ -233,6 +236,7 @@ class TerminalCommandLogRepository:
"command_hash": row.command_hash,
"last_used": row.max_created,
"execution_count": row.execution_count,
"is_pinned": bool(row.is_pinned),
}
for row in rows
]
+14
View File
@@ -128,6 +128,20 @@ class TerminalSessionRepository:
).order_by(TerminalSession.created_at.desc())
)
return list(result.scalars().all())
async def list_active_for_host(self, host_id: str) -> List[TerminalSession]:
"""List all active sessions for a specific host."""
now = datetime.now(timezone.utc)
result = await self.session.execute(
select(TerminalSession).where(
and_(
TerminalSession.host_id == host_id,
TerminalSession.status == SESSION_STATUS_ACTIVE,
TerminalSession.expires_at > now
)
).order_by(TerminalSession.created_at.desc())
)
return list(result.scalars().all())
async def list_all_active(self) -> List[TerminalSession]:
"""List all active sessions (for admin/GC)."""