fix: terminal left shift and instance naming scheme

- Debounce terminal ResizeObserver (100ms) and only send resize when cols/rows actually change
- Send initial resize on WebSocket connect/reconnect to prevent PTY default 80x24 shift
- Replace random hex instance names with sequential project-tool-NNN naming
- Add _sanitize_name() and _generate_instance_name() helpers for readable Docker names
This commit is contained in:
Developer
2026-06-02 12:11:19 +00:00
parent 7000f2075d
commit 5a8eca814d
2 changed files with 63 additions and 5 deletions
+39 -2
View File
@@ -2,6 +2,7 @@
import logging
import os
import re
import uuid
from datetime import datetime
@@ -206,6 +207,42 @@ async def _get_owned_project(
return project
def _sanitize_name(name: str) -> str:
"""Sanitize a string for use in Docker/container names."""
sanitized = re.sub(r"[^a-z0-9-]", "-", name.lower())
sanitized = re.sub(r"-+", "-", sanitized)
return sanitized.strip("-")
async def _generate_instance_name(
session: AsyncSession,
project_name: str,
tool_type_name: str,
) -> str:
"""Generate a unique instance name: project-tool-NUM.
Args:
session: Database session.
project_name: Name of the project.
tool_type_name: Name of the tool type.
Returns:
A unique instance name with a sequential 3-digit number.
"""
base = f"{_sanitize_name(project_name)}-{_sanitize_name(tool_type_name)}"
base = base.strip("-") or "instance"
result = await session.execute(
select(ToolInstance.name).where(ToolInstance.name.like(f"{base}-%"))
)
names = result.scalars().all()
max_num = 0
for name in names:
parts = name.rsplit("-", 1)
if len(parts) == 2 and parts[0] == base and parts[1].isdigit():
max_num = max(max_num, int(parts[1]))
return f"{base}-{max_num + 1:03d}"
@router.post(
"/{project_id}/repositories/{repo_id}/instances",
summary="Create tool instance",
@@ -278,8 +315,8 @@ async def create_instance(
)
try:
# Generate unique name
instance_name = f"{tool_type.name}-{repo.name}-{uuid.uuid4().hex[:8]}"
# Generate unique name: project-tool-NUM
instance_name = await _generate_instance_name(session, _project.name, tool_type.name)
instance_display = data.display_name or f"{tool_type.display_name} - {repo.name}"
# Create instance directory