mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-30 06:12:06 +00:00
feat: add feature editing capability for pending/in-progress features
Add the ability for users to edit features that are not yet completed,
allowing them to provide corrections or additional instructions when the
agent is stuck or implementing a feature incorrectly.
Backend changes:
- Add FeatureUpdate schema in server/schemas.py with optional fields
- Add PATCH /api/projects/{project_name}/features/{feature_id} endpoint
- Validate that completed features (passes=True) cannot be edited
Frontend changes:
- Add FeatureUpdate type in ui/src/lib/types.ts
- Add updateFeature() API function in ui/src/lib/api.ts
- Add useUpdateFeature() React Query mutation hook
- Create EditFeatureForm.tsx component with pre-filled form values
- Update FeatureModal.tsx with Edit button for non-completed features
The edit form allows modifying category, name, description, priority,
and test steps. Save button is disabled until changes are detected.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ from ..schemas import (
|
||||
FeatureCreate,
|
||||
FeatureListResponse,
|
||||
FeatureResponse,
|
||||
FeatureUpdate,
|
||||
)
|
||||
from ..utils.validation import validate_project_name
|
||||
|
||||
@@ -217,6 +218,63 @@ async def get_feature(project_name: str, feature_id: int):
|
||||
raise HTTPException(status_code=500, detail="Database error occurred")
|
||||
|
||||
|
||||
@router.patch("/{feature_id}", response_model=FeatureResponse)
|
||||
async def update_feature(project_name: str, feature_id: int, update: FeatureUpdate):
|
||||
"""
|
||||
Update a feature's details.
|
||||
|
||||
Only features that are not yet completed (passes=False) can be edited.
|
||||
This allows users to provide corrections or additional instructions
|
||||
when the agent is stuck or implementing a feature incorrectly.
|
||||
"""
|
||||
project_name = validate_project_name(project_name)
|
||||
project_dir = _get_project_path(project_name)
|
||||
|
||||
if not project_dir:
|
||||
raise HTTPException(status_code=404, detail=f"Project '{project_name}' not found in registry")
|
||||
|
||||
if not project_dir.exists():
|
||||
raise HTTPException(status_code=404, detail="Project directory not found")
|
||||
|
||||
_, Feature = _get_db_classes()
|
||||
|
||||
try:
|
||||
with get_db_session(project_dir) as session:
|
||||
feature = session.query(Feature).filter(Feature.id == feature_id).first()
|
||||
|
||||
if not feature:
|
||||
raise HTTPException(status_code=404, detail=f"Feature {feature_id} not found")
|
||||
|
||||
# Prevent editing completed features
|
||||
if feature.passes:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Cannot edit a completed feature. Features marked as done are immutable."
|
||||
)
|
||||
|
||||
# Apply updates for non-None fields
|
||||
if update.category is not None:
|
||||
feature.category = update.category
|
||||
if update.name is not None:
|
||||
feature.name = update.name
|
||||
if update.description is not None:
|
||||
feature.description = update.description
|
||||
if update.steps is not None:
|
||||
feature.steps = update.steps
|
||||
if update.priority is not None:
|
||||
feature.priority = update.priority
|
||||
|
||||
session.commit()
|
||||
session.refresh(feature)
|
||||
|
||||
return feature_to_response(feature)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception:
|
||||
logger.exception("Failed to update feature")
|
||||
raise HTTPException(status_code=500, detail="Failed to update feature")
|
||||
|
||||
|
||||
@router.delete("/{feature_id}")
|
||||
async def delete_feature(project_name: str, feature_id: int):
|
||||
"""Delete a feature."""
|
||||
|
||||
@@ -87,6 +87,15 @@ class FeatureCreate(FeatureBase):
|
||||
priority: int | None = None
|
||||
|
||||
|
||||
class FeatureUpdate(BaseModel):
|
||||
"""Request schema for updating a feature (partial updates allowed)."""
|
||||
category: str | None = None
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
steps: list[str] | None = None
|
||||
priority: int | None = None
|
||||
|
||||
|
||||
class FeatureResponse(FeatureBase):
|
||||
"""Response schema for a feature."""
|
||||
id: int
|
||||
|
||||
Reference in New Issue
Block a user