MCPcopy Create free account
hub / github.com/AutoForgeAI/autoforge / add_dependency

Function add_dependency

server/routers/features.py:583–640  ·  view source on GitHub ↗

Add a dependency relationship between features. The dep_id feature must be completed before feature_id can be started. Validates: self-reference, existence, circular dependencies, max limit.

(project_name: str, feature_id: int, dep_id: int)

Source from the content-addressed store, hash-verified

581
582@router.post("/{feature_id}/dependencies/{dep_id}")
583async def add_dependency(project_name: str, feature_id: int, dep_id: int):
584 """Add a dependency relationship between features.
585
586 The dep_id feature must be completed before feature_id can be started.
587 Validates: self-reference, existence, circular dependencies, max limit.
588 """
589 project_name = validate_project_name(project_name)
590
591 # Security: Self-reference check
592 if feature_id == dep_id:
593 raise HTTPException(status_code=400, detail="A feature cannot depend on itself")
594
595 project_dir = _get_project_path(project_name)
596
597 if not project_dir:
598 raise HTTPException(status_code=404, detail=f"Project '{project_name}' not found in registry")
599
600 if not project_dir.exists():
601 raise HTTPException(status_code=404, detail="Project directory not found")
602
603 would_create_circular_dependency, MAX_DEPENDENCIES_PER_FEATURE = _get_dependency_resolver()
604 _, Feature = _get_db_classes()
605
606 try:
607 with get_db_session(project_dir) as session:
608 feature = session.query(Feature).filter(Feature.id == feature_id).first()
609 dependency = session.query(Feature).filter(Feature.id == dep_id).first()
610
611 if not feature:
612 raise HTTPException(status_code=404, detail=f"Feature {feature_id} not found")
613 if not dependency:
614 raise HTTPException(status_code=404, detail=f"Dependency {dep_id} not found")
615
616 current_deps = feature.dependencies or []
617
618 # Security: Limit check
619 if len(current_deps) >= MAX_DEPENDENCIES_PER_FEATURE:
620 raise HTTPException(status_code=400, detail=f"Maximum {MAX_DEPENDENCIES_PER_FEATURE} dependencies allowed")
621
622 if dep_id in current_deps:
623 raise HTTPException(status_code=400, detail="Dependency already exists")
624
625 # Security: Circular dependency check
626 # source_id = feature_id (gaining dep), target_id = dep_id (being depended upon)
627 all_features = [f.to_dict() for f in session.query(Feature).all()]
628 if would_create_circular_dependency(all_features, feature_id, dep_id):
629 raise HTTPException(status_code=400, detail="Would create circular dependency")
630
631 current_deps.append(dep_id)
632 feature.dependencies = sorted(current_deps)
633 session.commit()
634
635 return {"success": True, "feature_id": feature_id, "dependencies": feature.dependencies}
636 except HTTPException:
637 raise
638 except Exception:
639 logger.exception("Failed to add dependency")
640 raise HTTPException(status_code=500, detail="Failed to add dependency")

Callers

nothing calls this directly

Calls 6

_get_dependency_resolverFunction · 0.85
_get_db_classesFunction · 0.85
get_db_sessionFunction · 0.85
validate_project_nameFunction · 0.70
to_dictMethod · 0.45

Tested by

no test coverage detected