140 lines
5.5 KiB
Python
140 lines
5.5 KiB
Python
|
|
"""Tool: Project Registry – Projekt-Registrierung, Status-Tracking und Historien-Snapshots."""
|
|||
|
|
import json
|
|||
|
|
|
|||
|
|
from helpers.tool import Tool, Response
|
|||
|
|
from usr.plugins.a0_software_orchestrator.helpers.exceptions import PluginDBError
|
|||
|
|
from usr.plugins.a0_software_orchestrator.helpers.db_state_store import (
|
|||
|
|
list_projects,
|
|||
|
|
get_project_detail,
|
|||
|
|
register_project,
|
|||
|
|
update_project_state,
|
|||
|
|
create_project_snapshot,
|
|||
|
|
list_project_snapshots,
|
|||
|
|
remove_project,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class ProjectRegistry(Tool):
|
|||
|
|
"""Tool for managing software project entries in the plugin's project database."""
|
|||
|
|
|
|||
|
|
async def execute(
|
|||
|
|
self,
|
|||
|
|
action: str = "list",
|
|||
|
|
name: str = "",
|
|||
|
|
git_url: str = "",
|
|||
|
|
description: str = "",
|
|||
|
|
tech_stack: str = "",
|
|||
|
|
status: str = "",
|
|||
|
|
phase: str = "",
|
|||
|
|
plan_mode: str = "",
|
|||
|
|
total_tasks: int = 0,
|
|||
|
|
completed_tasks: int = 0,
|
|||
|
|
open_errors: int = 0,
|
|||
|
|
trigger: str = "",
|
|||
|
|
commit_hash: str = "",
|
|||
|
|
**kwargs
|
|||
|
|
):
|
|||
|
|
try:
|
|||
|
|
if action == "list":
|
|||
|
|
projects = list_projects()
|
|||
|
|
return Response(
|
|||
|
|
message=json.dumps(projects, indent=2, ensure_ascii=False),
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "detail":
|
|||
|
|
if not name:
|
|||
|
|
return Response(message="Missing 'name' for detail action", break_loop=False)
|
|||
|
|
detail = get_project_detail(name)
|
|||
|
|
if not detail:
|
|||
|
|
return Response(message=f"Project '{name}' not found.", break_loop=False)
|
|||
|
|
return Response(
|
|||
|
|
message=json.dumps(detail, indent=2, ensure_ascii=False),
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "register":
|
|||
|
|
if not name:
|
|||
|
|
return Response(message="Missing 'name' for register action", break_loop=False)
|
|||
|
|
if not git_url:
|
|||
|
|
return Response(message="Missing 'git_url' for register action", break_loop=False)
|
|||
|
|
project_id = register_project(
|
|||
|
|
name=name,
|
|||
|
|
git_url=git_url,
|
|||
|
|
description=description,
|
|||
|
|
tech_stack=tech_stack or "{}",
|
|||
|
|
status=status or "active",
|
|||
|
|
phase=phase or "intake"
|
|||
|
|
)
|
|||
|
|
return Response(
|
|||
|
|
message=f"Project '{name}' registered successfully (id={project_id}, git_url={git_url}).",
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "update":
|
|||
|
|
if not name:
|
|||
|
|
return Response(message="Missing 'name' for update action", break_loop=False)
|
|||
|
|
fields = {}
|
|||
|
|
for field in ["status", "phase", "plan_mode"]:
|
|||
|
|
val = kwargs.get(field, "")
|
|||
|
|
if val:
|
|||
|
|
fields[field] = val
|
|||
|
|
for field in ["total_tasks", "completed_tasks", "open_errors"]:
|
|||
|
|
val = kwargs.get(field)
|
|||
|
|
if val is not None:
|
|||
|
|
fields[field] = int(val)
|
|||
|
|
if "last_active_at" in kwargs:
|
|||
|
|
fields["last_active_at"] = kwargs["last_active_at"]
|
|||
|
|
if "completed_at" in kwargs:
|
|||
|
|
fields["completed_at"] = kwargs["completed_at"]
|
|||
|
|
if not fields:
|
|||
|
|
return Response(message="No fields to update.", break_loop=False)
|
|||
|
|
update_project_state(name, **fields)
|
|||
|
|
return Response(
|
|||
|
|
message=f"Project '{name}' updated.",
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "snapshot":
|
|||
|
|
if not name:
|
|||
|
|
return Response(message="Missing 'name' for snapshot action", break_loop=False)
|
|||
|
|
snapshot_id = create_project_snapshot(
|
|||
|
|
name=name,
|
|||
|
|
trigger=trigger or "manual",
|
|||
|
|
commit_hash=commit_hash or ""
|
|||
|
|
)
|
|||
|
|
return Response(
|
|||
|
|
message=f"Snapshot saved for project '{name}' (trigger: {trigger or 'manual'}).",
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "history":
|
|||
|
|
if not name:
|
|||
|
|
return Response(message="Missing 'name' for history action", break_loop=False)
|
|||
|
|
snapshots = list_project_snapshots(name)
|
|||
|
|
return Response(
|
|||
|
|
message=json.dumps(snapshots, indent=2, ensure_ascii=False),
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "remove":
|
|||
|
|
if not name:
|
|||
|
|
return Response(message="Missing 'name' for remove action", break_loop=False)
|
|||
|
|
remove_project(name)
|
|||
|
|
return Response(
|
|||
|
|
message=f"Project '{name}' removed from registry (snapshots also deleted).",
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
else:
|
|||
|
|
supported = ["list", "detail", "register", "update", "snapshot", "history", "remove"]
|
|||
|
|
return Response(
|
|||
|
|
message=f"Unknown action '{action}'. Supported: {', '.join(supported)}",
|
|||
|
|
break_loop=False
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
except PluginDBError as e:
|
|||
|
|
return Response(message=f"Database error: {e}", break_loop=False)
|
|||
|
|
except ValueError as e:
|
|||
|
|
return Response(message=f"Error: {e}", break_loop=False)
|