From c6d62f84daac5d1e9073a2fec831253a8aa384a0 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Wed, 3 Jun 2026 23:35:16 +0200 Subject: [PATCH] fix: port useful fixes from overwritten main merge From ae02e97 ('fix: tunnel URLs, session naming, git control bar placement'): 1. Tunnel URL regex: exclude api.trycloudflare.com from pattern. Real tunnel subdomains are 10+ random chars. Prevents matching the Cloudflare API endpoint instead of the actual tunnel URL. 2. Session auto-numbering: when user doesn't provide a display_name, auto-generate 'project / repo / tool_type #N' where N increments for each existing instance with the same project/repo/tool_type. Prevents confusing duplicate display names in the sidebar. These fixes were lost when main's merge was overwritten. Ported to our clean dev codebase. Quality gates: py_compile passed, ruff passed on tool_instances.py and tunnel.py. --- apps/api/src/api/tool_instances.py | 22 +++++++++++++++++++--- apps/api/src/services/tunnel.py | 4 +++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/apps/api/src/api/tool_instances.py b/apps/api/src/api/tool_instances.py index eca5437..7898fe2 100644 --- a/apps/api/src/api/tool_instances.py +++ b/apps/api/src/api/tool_instances.py @@ -893,9 +893,25 @@ async def create_instance( # Generate unique name instance_name = f"{tool_type.name}-{repo.name}-{uuid.uuid4().hex[:8]}" - instance_display = ( - data.display_name or f"{tool_type.display_name} - {repo.name}" - ) + + # Auto-generate display name with numbering when duplicates exist + if data.display_name: + instance_display = data.display_name + else: + auto_name = f"{_project.name} / {repo.name} / {tool_type.display_name}" + result = await session.execute( + select(ToolInstance).where( + ToolInstance.project_id == project_id, + ToolInstance.repository_id == repo_id, + ToolInstance.tool_type_id == tool_type_id, + ToolInstance.owner_id == user_id, + ) + ) + existing_count = len(result.scalars().all()) + if existing_count > 0: + instance_display = f"{auto_name} #{existing_count + 1}" + else: + instance_display = auto_name # Create instance directory instance_dir = ensure_instance_directory(instance_name) diff --git a/apps/api/src/services/tunnel.py b/apps/api/src/services/tunnel.py index 6a2c468..4c4d907 100644 --- a/apps/api/src/services/tunnel.py +++ b/apps/api/src/services/tunnel.py @@ -133,7 +133,9 @@ def start_tunnel( logger.debug("Tunnel container started: %s", container_id) # Wait for URL to appear in logs - url_pattern = re.compile(r"https://[a-z0-9-]+\.trycloudflare\.com") + # Exclude api.trycloudflare.com which is the Cloudflare API endpoint, + # not a tunnel URL. Real tunnel URLs have random subdomains (10+ chars). + url_pattern = re.compile(r"https://(?!api\.)[a-z0-9-]{10,}\.trycloudflare\.com") start_time = __import__("time").time() url: str | None = None combined_logs = ""