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

Function create_features_bulk

server/routers/features.py:221–306  ·  view source on GitHub ↗

Create multiple features at once. Features are assigned sequential priorities starting from: - starting_priority if specified (must be >= 1) - max(existing priorities) + 1 if not specified This is useful for: - Expanding a project with new features via AI - Importing f

(project_name: str, bulk: FeatureBulkCreate)

Source from the content-addressed store, hash-verified

219
220@router.post("/bulk", response_model=FeatureBulkCreateResponse)
221async def create_features_bulk(project_name: str, bulk: FeatureBulkCreate):
222 """
223 Create multiple features at once.
224
225 Features are assigned sequential priorities starting from:
226 - starting_priority if specified (must be >= 1)
227 - max(existing priorities) + 1 if not specified
228
229 This is useful for:
230 - Expanding a project with new features via AI
231 - Importing features from external sources
232 - Batch operations
233
234 Returns:
235 {"created": N, "features": [...]}
236 """
237 project_name = validate_project_name(project_name)
238 project_dir = _get_project_path(project_name)
239
240 if not project_dir:
241 raise HTTPException(status_code=404, detail=f"Project '{project_name}' not found in registry")
242
243 if not project_dir.exists():
244 raise HTTPException(status_code=404, detail="Project directory not found")
245
246 if not bulk.features:
247 return FeatureBulkCreateResponse(created=0, features=[])
248
249 # Validate starting_priority if provided
250 if bulk.starting_priority is not None and bulk.starting_priority < 1:
251 raise HTTPException(status_code=400, detail="starting_priority must be >= 1")
252
253 _, Feature = _get_db_classes()
254
255 try:
256 with get_db_session(project_dir) as session:
257 # Determine starting priority
258 # Note: SQLite uses file-level locking, not row-level locking, so we rely on
259 # SQLite's transaction isolation. Concurrent bulk creates may get overlapping
260 # priorities, but this is acceptable since priorities can be reordered.
261 if bulk.starting_priority is not None:
262 current_priority = bulk.starting_priority
263 else:
264 max_priority_feature = (
265 session.query(Feature)
266 .order_by(Feature.priority.desc())
267 .first()
268 )
269 current_priority = (max_priority_feature.priority + 1) if max_priority_feature else 1
270
271 created_ids = []
272
273 for feature_data in bulk.features:
274 db_feature = Feature(
275 priority=current_priority,
276 category=feature_data.category,
277 name=feature_data.name,
278 description=feature_data.description,

Callers

nothing calls this directly

Calls 6

FeatureClass · 0.90
_get_db_classesFunction · 0.85
get_db_sessionFunction · 0.85
feature_to_responseFunction · 0.85
validate_project_nameFunction · 0.70

Tested by

no test coverage detected