feat(mma): Enable manual ticket approval via Hook API for Step Mode
This commit is contained in:
@@ -267,3 +267,7 @@ class ApiHookClient:
|
|||||||
"""Mutates the MMA DAG (Directed Acyclic Graph) structure."""
|
"""Mutates the MMA DAG (Directed Acyclic Graph) structure."""
|
||||||
return self._make_request('POST', '/api/mma/dag/mutate', data=data) or {}
|
return self._make_request('POST', '/api/mma/dag/mutate', data=data) or {}
|
||||||
|
|
||||||
|
def approve_mma_ticket(self, ticket_id: str) -> dict:
|
||||||
|
"""Manually approves a specific ticket for execution in Step Mode."""
|
||||||
|
return self._make_request('POST', '/api/mma/ticket/approve', data={"ticket_id": ticket_id}) or {}
|
||||||
|
|
||||||
|
|||||||
+18
-1
@@ -605,7 +605,7 @@ class HookHandler(BaseHTTPRequestHandler):
|
|||||||
elif self.path == "/api/mma/dag/mutate":
|
elif self.path == "/api/mma/dag/mutate":
|
||||||
def mutate_dag():
|
def mutate_dag():
|
||||||
try:
|
try:
|
||||||
func = _get_app_attr(app, "_mutate_dag")
|
func = _get_app_attr(app, "mutate_dag")
|
||||||
if func: func(data)
|
if func: func(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stderr.write(f"[DEBUG] Hook API mutate_dag error: {e}\n")
|
sys.stderr.write(f"[DEBUG] Hook API mutate_dag error: {e}\n")
|
||||||
@@ -618,6 +618,23 @@ class HookHandler(BaseHTTPRequestHandler):
|
|||||||
self.send_header("Content-Type", "application/json")
|
self.send_header("Content-Type", "application/json")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(json.dumps({"status": "queued"}).encode("utf-8"))
|
self.wfile.write(json.dumps({"status": "queued"}).encode("utf-8"))
|
||||||
|
elif self.path == "/api/mma/ticket/approve":
|
||||||
|
ticket_id = data.get("ticket_id")
|
||||||
|
def approve_ticket():
|
||||||
|
try:
|
||||||
|
func = _get_app_attr(app, "approve_ticket")
|
||||||
|
if func: func(ticket_id)
|
||||||
|
except Exception as e:
|
||||||
|
sys.stderr.write(f"[DEBUG] Hook API approve_ticket error: {e}\n")
|
||||||
|
sys.stderr.flush()
|
||||||
|
lock = _get_app_attr(app, "_pending_gui_tasks_lock")
|
||||||
|
tasks = _get_app_attr(app, "_pending_gui_tasks")
|
||||||
|
if lock and tasks is not None:
|
||||||
|
with lock: tasks.append({"action": "custom_callback", "callback": approve_ticket})
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-Type", "application/json")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps({"status": "queued"}).encode("utf-8"))
|
||||||
else:
|
else:
|
||||||
self.send_response(404)
|
self.send_response(404)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|||||||
@@ -2780,6 +2780,18 @@ class AppController:
|
|||||||
self.files.append(item)
|
self.files.append(item)
|
||||||
self._refresh_from_project()
|
self._refresh_from_project()
|
||||||
|
|
||||||
|
def approve_ticket(self, ticket_id: str) -> None:
|
||||||
|
"""Manually approves a ticket for execution."""
|
||||||
|
if self.engine and self.engine.engine:
|
||||||
|
self.engine.engine.approve_task(ticket_id)
|
||||||
|
else:
|
||||||
|
# Fallback if engine not running
|
||||||
|
for t in self.active_tickets:
|
||||||
|
if t.get('id') == ticket_id:
|
||||||
|
t['status'] = 'in_progress'
|
||||||
|
break
|
||||||
|
self._push_mma_state_update()
|
||||||
|
|
||||||
def mutate_dag(self, data: dict) -> None:
|
def mutate_dag(self, data: dict) -> None:
|
||||||
"""Modifies task dependencies."""
|
"""Modifies task dependencies."""
|
||||||
ticket_id = data.get("ticket_id")
|
ticket_id = data.get("ticket_id")
|
||||||
|
|||||||
+1
-1
@@ -3450,7 +3450,7 @@ def hello():
|
|||||||
def bulk_execute(self) -> None:
|
def bulk_execute(self) -> None:
|
||||||
for tid in self.ui_selected_tickets:
|
for tid in self.ui_selected_tickets:
|
||||||
t = next((t for t in self.active_tickets if str(t.get('id', '')) == tid), None)
|
t = next((t for t in self.active_tickets if str(t.get('id', '')) == tid), None)
|
||||||
if t: t['status'] = 'ready'
|
if t: t['status'] = 'in_progress'
|
||||||
self._push_mma_state_update()
|
self._push_mma_state_update()
|
||||||
|
|
||||||
def bulk_skip(self) -> None:
|
def bulk_skip(self) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user