feat: improve session naming, project display, rename support, tab titles
Backend:
- sessions.py: include workspace_name in session response
- instance_service.py: auto-generate display names as
'Project / Workspace / Tool #N' instead of 'Workspace / Tool #N'
- instance_service.py: add rename_tool_instance() service function
- tool_instances.py: add PATCH /instances/{id} endpoint for renaming
display_name
Frontend:
- api/sessions.ts: add workspace_name to Session type, add renameInstance()
- use-instance-actions.ts: add handleRename, set document.title when opening
- session-card.tsx: click-to-edit display_name inline; always show project
context line (Project / Workspace or Repo / Tool)
- session-list.tsx: pass through onRename prop
- SessionsPage.tsx: wire handleRename to SessionCard and SessionList
- app-shell.tsx: sidebar tooltip includes workspace or repo name
- use-terminal-page.ts: set document.title based on active terminal session
Quality gates: py_compile all backend files pass, tsc --noEmit pass,
npm run build pass, 82/82 tests pass
This commit is contained in:
@@ -13,7 +13,8 @@ from fastapi import HTTPException, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.models import ConfigProfile, GitRepository, SSHKey, ToolInstance, ToolType
|
||||
from src.models import ConfigProfile, GitRepository, Project, SSHKey, ToolInstance, ToolType
|
||||
from src.schemas.tool import CreateInstanceRequest, StartInstanceRequest
|
||||
from src.services.git.clone import check_dirty_state, clone_repository
|
||||
from src.services.config.config_profile_resolver import (
|
||||
ConfigProfileCycleError,
|
||||
@@ -935,8 +936,10 @@ async def create_tool_instance(
|
||||
if data.display_name:
|
||||
instance_display = data.display_name
|
||||
else:
|
||||
project = await session.get(Project, project_id)
|
||||
project_name = project.name if project else "Unknown"
|
||||
scope_name = workspace.name if workspace else repo.name
|
||||
auto_name = f"{scope_name} / {tool_type.display_name}"
|
||||
auto_name = f"{project_name} / {scope_name} / {tool_type.display_name}"
|
||||
|
||||
if workspace:
|
||||
count_query = (
|
||||
@@ -2161,3 +2164,25 @@ async def stop_tool_instance(
|
||||
message="Instance stopped",
|
||||
)
|
||||
return {"status": instance.status}
|
||||
|
||||
|
||||
async def rename_tool_instance(
|
||||
session: AsyncSession,
|
||||
user_id: uuid.UUID,
|
||||
project_id: uuid.UUID,
|
||||
repo_id: uuid.UUID,
|
||||
instance_id: uuid.UUID,
|
||||
display_name: str,
|
||||
) -> ToolInstance:
|
||||
"""Rename a tool instance (update display_name only)."""
|
||||
instance = await session.get(ToolInstance, instance_id)
|
||||
if instance is None or instance.repository_id != repo_id:
|
||||
raise ValueError("instance not found")
|
||||
if instance.owner_id != user_id:
|
||||
raise ValueError("not authorized")
|
||||
|
||||
instance.display_name = display_name.strip()
|
||||
await session.commit()
|
||||
await session.refresh(instance)
|
||||
return instance
|
||||
|
||||
|
||||
Reference in New Issue
Block a user