feat(mma): Complete Phase 7 implementation: MMA Dashboard, HITL Step Modal, and Memory Mutator
This commit is contained in:
@@ -102,17 +102,50 @@ class ConductorEngine:
|
||||
model_name="gemini-2.5-flash-lite",
|
||||
messages=[]
|
||||
)
|
||||
run_worker_lifecycle(ticket, context)
|
||||
run_worker_lifecycle(ticket, context, event_queue=self.event_queue)
|
||||
await self._push_state(active_tier="Tier 2 (Tech Lead)")
|
||||
|
||||
def confirm_execution(payload: str) -> bool:
|
||||
def confirm_execution(payload: str, event_queue: events.AsyncEventQueue, ticket_id: str) -> bool:
|
||||
"""
|
||||
Placeholder for external confirmation function.
|
||||
In a real scenario, this might trigger a UI prompt.
|
||||
Pushes an approval request to the GUI and waits for response.
|
||||
"""
|
||||
return True
|
||||
import threading
|
||||
import time
|
||||
import asyncio
|
||||
# We use a list container so the GUI can inject the actual Dialog object back to us
|
||||
# since the dialog is created in the GUI thread.
|
||||
dialog_container = [None]
|
||||
|
||||
task = {
|
||||
"action": "mma_step_approval",
|
||||
"ticket_id": ticket_id,
|
||||
"payload": payload,
|
||||
"dialog_container": dialog_container
|
||||
}
|
||||
|
||||
# Push to queue
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
if loop.is_running():
|
||||
asyncio.run_coroutine_threadsafe(event_queue.put("mma_step_approval", task), loop)
|
||||
else:
|
||||
event_queue._queue.put_nowait(("mma_step_approval", task))
|
||||
except Exception:
|
||||
# Fallback if no loop
|
||||
event_queue._queue.put_nowait(("mma_step_approval", task))
|
||||
|
||||
def run_worker_lifecycle(ticket: Ticket, context: WorkerContext, context_files: List[str] = None):
|
||||
# Wait for the GUI to create the dialog and for the user to respond
|
||||
start = time.time()
|
||||
while dialog_container[0] is None and time.time() - start < 60:
|
||||
time.sleep(0.1)
|
||||
|
||||
if dialog_container[0]:
|
||||
approved, final_payload = dialog_container[0].wait()
|
||||
return approved
|
||||
|
||||
return False
|
||||
|
||||
def run_worker_lifecycle(ticket: Ticket, context: WorkerContext, context_files: List[str] = None, event_queue: events.AsyncEventQueue = None):
|
||||
"""
|
||||
Simulates the lifecycle of a single agent working on a ticket.
|
||||
Calls the AI client and updates the ticket status based on the response.
|
||||
@@ -150,11 +183,17 @@ def run_worker_lifecycle(ticket: Ticket, context: WorkerContext, context_files:
|
||||
|
||||
# In a real scenario, we would pass md_content from the aggregator
|
||||
# and manage the conversation history in the context.
|
||||
# HITL Clutch: pass the queue and ticket_id to confirm_execution
|
||||
def clutch_callback(payload: str) -> bool:
|
||||
if not event_queue:
|
||||
return True
|
||||
return confirm_execution(payload, event_queue, ticket.id)
|
||||
|
||||
response = ai_client.send(
|
||||
md_content="",
|
||||
user_message=user_message,
|
||||
base_dir=".",
|
||||
pre_tool_callback=confirm_execution if ticket.step_mode else None,
|
||||
pre_tool_callback=clutch_callback if ticket.step_mode else None,
|
||||
qa_callback=ai_client.run_tier4_analysis
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user