fix: decouple project name from folder path in project creation

Remove automatic subfolder creation when creating projects. Users now
select the exact folder they want to use, enabling support for existing
projects without requiring folder names to match project names.

Changes:
- NewProjectModal.tsx: Remove path concatenation that appended project
  name to selected folder. Update instruction text to clarify users
  select THE project folder, not a parent location.
- FolderBrowser.tsx: Add visual indicator "This folder will contain
  all project files" to clarify selection behavior.
- projects.py: Add duplicate path validation to prevent multiple
  projects from registering the same directory. Includes case-insensitive
  path comparison on Windows for proper cross-platform support.

This allows users to:
- Use Auto Coder on existing projects by selecting their folder directly
- Have project names that differ from folder names (name is a registry label)
- Get clear feedback when a path is already registered under another name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Auto
2026-01-11 11:30:34 +02:00
parent b18ca80174
commit aede8f720e
3 changed files with 25 additions and 5 deletions

View File

@@ -8,6 +8,7 @@ Uses project registry for path lookups instead of fixed generations/ directory.
import re
import shutil
import sys
from pathlib import Path
from fastapi import APIRouter, HTTPException
@@ -131,7 +132,7 @@ async def list_projects():
async def create_project(project: ProjectCreate):
"""Create a new project at the specified path."""
_init_imports()
register_project, _, get_project_path, _, _ = _get_registry_functions()
register_project, _, get_project_path, list_registered_projects, _ = _get_registry_functions()
name = validate_project_name(project.name)
project_path = Path(project.path).resolve()
@@ -144,6 +145,22 @@ async def create_project(project: ProjectCreate):
detail=f"Project '{name}' already exists at {existing}"
)
# Check if path already registered under a different name
all_projects = list_registered_projects()
for existing_name, info in all_projects.items():
existing_path = Path(info["path"]).resolve()
# Case-insensitive comparison on Windows
if sys.platform == "win32":
paths_match = str(existing_path).lower() == str(project_path).lower()
else:
paths_match = existing_path == project_path
if paths_match:
raise HTTPException(
status_code=409,
detail=f"Path '{project_path}' is already registered as project '{existing_name}'"
)
# Security: Check if path is in a blocked location
from .filesystem import is_path_blocked
if is_path_blocked(project_path):

View File

@@ -304,6 +304,11 @@ export function FolderBrowser({ onSelect, onCancel, initialPath }: FolderBrowser
<div className="mb-3 p-2 bg-[var(--color-neo-bg)] rounded border-2 border-[var(--color-neo-border)]">
<div className="text-xs text-[#4a4a4a] mb-1">Selected path:</div>
<div className="font-mono text-sm truncate text-[#1a1a1a]">{selectedPath || 'No folder selected'}</div>
{selectedPath && (
<div className="text-xs text-[var(--color-neo-text-secondary)] mt-2 italic">
This folder will contain all project files
</div>
)}
</div>
{/* Actions */}

View File

@@ -75,9 +75,7 @@ export function NewProjectModal({
}
const handleFolderSelect = (path: string) => {
// Append project name to the selected path
const fullPath = path.endsWith('/') ? `${path}${projectName.trim()}` : `${path}/${projectName.trim()}`
setProjectPath(fullPath)
setProjectPath(path) // Use selected path directly - no subfolder creation
changeStep('method')
}
@@ -218,7 +216,7 @@ export function NewProjectModal({
Select Project Location
</h2>
<p className="text-sm text-[#4a4a4a]">
A folder named <span className="font-bold font-mono">{projectName}</span> will be created inside the selected directory
Select the folder to use for project <span className="font-bold font-mono">{projectName}</span>. Create a new folder or choose an existing one.
</p>
</div>
</div>