mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-30 06:12:06 +00:00
feat: add project reset functionality with quick and full reset options
Add the ability to reset a project to its initial state with two options:
- Quick Reset: Clears features.db, assistant.db, and settings files while
preserving app spec and prompts
- Full Reset: Deletes everything including prompts directory, triggering
the setup wizard for project reconfiguration
Backend changes:
- Add POST /{name}/reset endpoint to projects router with full_reset query param
- Validate agent lock file to prevent reset while agent is running (409 Conflict)
- Dispose database engines before deleting files to release Windows file locks
- Add engine caching to api/database.py for better connection management
- Add dispose_engine() functions to both database modules
- Delete WAL mode journal files (*.db-wal, *.db-shm) during reset
Frontend changes:
- Add ResetProjectModal component with toggle between Quick/Full reset modes
- Add ProjectSetupRequired component shown when has_spec is false
- Add resetProject API function and useResetProject React Query hook
- Integrate reset button in header (disabled when agent running)
- Add 'R' keyboard shortcut to open reset modal
- Show ProjectSetupRequired when project needs setup after full reset
This implements the feature from PR #4 directly on master to avoid merge
conflicts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -336,12 +336,20 @@ def create_database(project_dir: Path) -> tuple:
|
||||
"""
|
||||
Create database and return engine + session maker.
|
||||
|
||||
Uses a cache to avoid creating new engines for each request, which improves
|
||||
performance by reusing database connections.
|
||||
|
||||
Args:
|
||||
project_dir: Directory containing the project
|
||||
|
||||
Returns:
|
||||
Tuple of (engine, SessionLocal)
|
||||
"""
|
||||
cache_key = project_dir.as_posix()
|
||||
|
||||
if cache_key in _engine_cache:
|
||||
return _engine_cache[cache_key]
|
||||
|
||||
db_url = get_database_url(project_dir)
|
||||
engine = create_engine(db_url, connect_args={
|
||||
"check_same_thread": False,
|
||||
@@ -369,12 +377,39 @@ def create_database(project_dir: Path) -> tuple:
|
||||
_migrate_add_schedules_tables(engine)
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
# Cache the engine and session maker
|
||||
_engine_cache[cache_key] = (engine, SessionLocal)
|
||||
|
||||
return engine, SessionLocal
|
||||
|
||||
|
||||
def dispose_engine(project_dir: Path) -> bool:
|
||||
"""Dispose of and remove the cached engine for a project.
|
||||
|
||||
This closes all database connections, releasing file locks on Windows.
|
||||
Should be called before deleting the database file.
|
||||
|
||||
Returns:
|
||||
True if an engine was disposed, False if no engine was cached.
|
||||
"""
|
||||
cache_key = project_dir.as_posix()
|
||||
|
||||
if cache_key in _engine_cache:
|
||||
engine, _ = _engine_cache.pop(cache_key)
|
||||
engine.dispose()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Global session maker - will be set when server starts
|
||||
_session_maker: Optional[sessionmaker] = None
|
||||
|
||||
# Engine cache to avoid creating new engines for each request
|
||||
# Key: project directory path (as posix string), Value: (engine, SessionLocal)
|
||||
_engine_cache: dict[str, tuple] = {}
|
||||
|
||||
|
||||
def set_session_maker(session_maker: sessionmaker) -> None:
|
||||
"""Set the global session maker."""
|
||||
|
||||
Reference in New Issue
Block a user