feat(mma): complete Phase 6 and finalize Comprehensive GUI UX track
- Implement Live Worker Streaming: wire ai_client.comms_log_callback to Tier 3 streams - Add Parallel DAG Execution using asyncio.gather for non-dependent tickets - Implement Automatic Retry with Model Escalation (Flash-Lite -> Flash -> Pro) - Add Tier Model Configuration UI to MMA Dashboard with project TOML persistence - Fix FPS reporting in PerformanceMonitor to prevent transient 0.0 values - Update Ticket model with retry_count and dictionary-like access - Stabilize Gemini CLI integration tests and handle script approval events in simulations - Finalize and verify all 6 phases of the implementation plan
This commit is contained in:
212
ai_client.py
212
ai_client.py
@@ -268,6 +268,8 @@ def set_provider(provider: str, model: str) -> None:
|
||||
else:
|
||||
_model = model
|
||||
|
||||
def get_provider() -> str:
|
||||
return _provider
|
||||
def cleanup() -> None:
|
||||
"""Called on application exit to prevent orphaned caches from billing."""
|
||||
global _gemini_client, _gemini_cache
|
||||
@@ -783,22 +785,29 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str,
|
||||
for i, fc in enumerate(calls):
|
||||
name, args = fc.name, dict(fc.args)
|
||||
# Check for tool confirmation if callback is provided
|
||||
if pre_tool_callback:
|
||||
payload_str = json.dumps({"tool": name, "args": args})
|
||||
if not pre_tool_callback(payload_str):
|
||||
out = "USER REJECTED: tool execution cancelled"
|
||||
f_resps.append(types.Part.from_function_response(name=name, response={"output": out}))
|
||||
log.append({"tool_use_id": name, "content": out})
|
||||
continue
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": name, "args": args, "round": r_idx})
|
||||
if name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": name, "args": args})
|
||||
out = mcp_client.dispatch(name, args)
|
||||
elif name == TOOL_NAME:
|
||||
out = ""
|
||||
tool_executed = False
|
||||
if name == TOOL_NAME and pre_tool_callback:
|
||||
scr = args.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "script": scr})
|
||||
out = _run_script(scr, base_dir, qa_callback)
|
||||
else: out = f"ERROR: unknown tool '{name}'"
|
||||
res = pre_tool_callback(scr, base_dir, qa_callback)
|
||||
if res is None:
|
||||
out = "USER REJECTED: tool execution cancelled"
|
||||
else:
|
||||
out = res
|
||||
tool_executed = True
|
||||
|
||||
if not tool_executed:
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": name, "args": args, "round": r_idx})
|
||||
if name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": name, "args": args})
|
||||
out = mcp_client.dispatch(name, args)
|
||||
elif name == TOOL_NAME:
|
||||
scr = args.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "script": scr})
|
||||
out = _run_script(scr, base_dir, qa_callback)
|
||||
else: out = f"ERROR: unknown tool '{name}'"
|
||||
|
||||
if i == len(calls) - 1:
|
||||
if file_items:
|
||||
file_items, changed = _reread_file_items(file_items)
|
||||
@@ -854,7 +863,7 @@ def _send_gemini_cli(md_content: str, user_message: str, base_dir: str,
|
||||
if isinstance(payload, list):
|
||||
send_payload = json.dumps(payload)
|
||||
|
||||
resp_data = adapter.send(send_payload, safety_settings=safety_settings, system_instruction=sys_instr, model=_model)
|
||||
resp_data = adapter.send(send_payload, safety_settings=safety_settings, system_instruction=sys_instr, model=_model, stream_callback=stream_callback)
|
||||
# Log any stderr from the CLI for transparency
|
||||
cli_stderr = resp_data.get("stderr", "")
|
||||
if cli_stderr:
|
||||
@@ -898,28 +907,30 @@ def _send_gemini_cli(md_content: str, user_message: str, base_dir: str,
|
||||
args = fc.get("args", {})
|
||||
call_id = fc.get("id")
|
||||
# Check for tool confirmation if callback is provided
|
||||
if pre_tool_callback:
|
||||
payload_str = json.dumps({"tool": name, "args": args})
|
||||
if not pre_tool_callback(payload_str):
|
||||
out = "USER REJECTED: tool execution cancelled"
|
||||
tool_results_for_cli.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": call_id,
|
||||
"name": name,
|
||||
"content": out
|
||||
})
|
||||
_append_comms("IN", "tool_result", {"name": name, "id": call_id, "output": out})
|
||||
continue
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": name, "args": args, "round": r_idx})
|
||||
if name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": name, "id": call_id, "args": args})
|
||||
out = mcp_client.dispatch(name, args)
|
||||
elif name == TOOL_NAME:
|
||||
out = ""
|
||||
tool_executed = False
|
||||
if name == TOOL_NAME and pre_tool_callback:
|
||||
scr = args.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "id": call_id, "script": scr})
|
||||
out = _run_script(scr, base_dir, qa_callback)
|
||||
else:
|
||||
out = f"ERROR: unknown tool '{name}'"
|
||||
res = pre_tool_callback(scr, base_dir, qa_callback)
|
||||
if res is None:
|
||||
out = "USER REJECTED: tool execution cancelled"
|
||||
else:
|
||||
out = res
|
||||
tool_executed = True
|
||||
|
||||
if not tool_executed:
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": name, "args": args, "round": r_idx})
|
||||
if name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": name, "id": call_id, "args": args})
|
||||
out = mcp_client.dispatch(name, args)
|
||||
elif name == TOOL_NAME:
|
||||
scr = args.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "id": call_id, "script": scr})
|
||||
out = _run_script(scr, base_dir, qa_callback)
|
||||
else:
|
||||
out = f"ERROR: unknown tool '{name}'"
|
||||
|
||||
if i == len(calls) - 1:
|
||||
if file_items:
|
||||
file_items, changed = _reread_file_items(file_items)
|
||||
@@ -1312,49 +1323,52 @@ def _send_anthropic(md_content: str, user_message: str, base_dir: str, file_item
|
||||
b_id = getattr(block, "id", "")
|
||||
b_input = getattr(block, "input", {})
|
||||
# Check for tool confirmation if callback is provided
|
||||
if pre_tool_callback:
|
||||
payload_str = json.dumps({"tool": b_name, "args": b_input})
|
||||
if not pre_tool_callback(payload_str):
|
||||
output = "USER REJECTED: tool execution cancelled"
|
||||
tool_results.append({
|
||||
"type": "tool_result",
|
||||
"tool_use_id": b_id,
|
||||
"content": output,
|
||||
})
|
||||
continue
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": b_name, "args": b_input, "round": round_idx})
|
||||
if b_name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": b_name, "id": b_id, "args": b_input})
|
||||
output = mcp_client.dispatch(b_name, b_input)
|
||||
_append_comms("IN", "tool_result", {"name": b_name, "id": b_id, "output": output})
|
||||
truncated = _truncate_tool_output(output)
|
||||
_cumulative_tool_bytes += len(truncated)
|
||||
tool_results.append({
|
||||
"type": "tool_result",
|
||||
"tool_use_id": b_id,
|
||||
"content": truncated,
|
||||
})
|
||||
events.emit("tool_execution", payload={"status": "completed", "tool": b_name, "result": output, "round": round_idx})
|
||||
elif b_name == TOOL_NAME:
|
||||
output = ""
|
||||
tool_executed = False
|
||||
if b_name == TOOL_NAME and pre_tool_callback:
|
||||
script = b_input.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {
|
||||
"name": TOOL_NAME,
|
||||
"id": b_id,
|
||||
"script": script,
|
||||
})
|
||||
output = _run_script(script, base_dir, qa_callback)
|
||||
_append_comms("IN", "tool_result", {
|
||||
"name": TOOL_NAME,
|
||||
"id": b_id,
|
||||
"output": output,
|
||||
})
|
||||
truncated = _truncate_tool_output(output)
|
||||
_cumulative_tool_bytes += len(truncated)
|
||||
tool_results.append({
|
||||
"type": "tool_result",
|
||||
"tool_use_id": b_id,
|
||||
"content": truncated,
|
||||
})
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "id": b_id, "script": script})
|
||||
res = pre_tool_callback(script, base_dir, qa_callback)
|
||||
if res is None:
|
||||
output = "USER REJECTED: tool execution cancelled"
|
||||
else:
|
||||
output = res
|
||||
tool_executed = True
|
||||
|
||||
if not tool_executed:
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": b_name, "args": b_input, "round": round_idx})
|
||||
if b_name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": b_name, "id": b_id, "args": b_input})
|
||||
output = mcp_client.dispatch(b_name, b_input)
|
||||
_append_comms("IN", "tool_result", {"name": b_name, "id": b_id, "output": output})
|
||||
elif b_name == TOOL_NAME:
|
||||
script = b_input.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {
|
||||
"name": TOOL_NAME,
|
||||
"id": b_id,
|
||||
"script": script,
|
||||
})
|
||||
output = _run_script(script, base_dir, qa_callback)
|
||||
_append_comms("IN", "tool_result", {
|
||||
"name": TOOL_NAME,
|
||||
"id": b_id,
|
||||
"output": output,
|
||||
})
|
||||
else:
|
||||
output = f"ERROR: unknown tool '{b_name}'"
|
||||
|
||||
truncated = _truncate_tool_output(output)
|
||||
_cumulative_tool_bytes += len(truncated)
|
||||
tool_results.append({
|
||||
"type": "tool_result",
|
||||
"tool_use_id": b_id,
|
||||
"content": truncated,
|
||||
})
|
||||
if not tool_executed:
|
||||
_append_comms("IN", "tool_result", {"name": b_name, "id": b_id, "output": output})
|
||||
events.emit("tool_execution", payload={"status": "completed", "tool": b_name, "result": output, "round": round_idx})
|
||||
else:
|
||||
# For pre_tool_callback tools, we've already logged comms
|
||||
events.emit("tool_execution", payload={"status": "completed", "tool": b_name, "result": output, "round": round_idx})
|
||||
if _cumulative_tool_bytes > _MAX_TOOL_OUTPUT_BYTES:
|
||||
tool_results.append({
|
||||
@@ -1560,28 +1574,32 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
||||
tool_args = json.loads(tool_args_str)
|
||||
except:
|
||||
tool_args = {}
|
||||
# Check for tool confirmation if callback is provided
|
||||
if pre_tool_callback:
|
||||
payload_str = json.dumps({"tool": tool_name, "args": tool_args})
|
||||
if not pre_tool_callback(payload_str):
|
||||
tool_output = "USER REJECTED: tool execution cancelled"
|
||||
tool_results_for_history.append({
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_id,
|
||||
"content": tool_output,
|
||||
})
|
||||
_append_comms("IN", "tool_result", {"name": tool_name, "id": tool_id, "output": tool_output})
|
||||
continue
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": tool_name, "args": tool_args, "round": round_idx})
|
||||
if tool_name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": tool_name, "id": tool_id, "args": tool_args})
|
||||
tool_output = mcp_client.dispatch(tool_name, tool_args)
|
||||
elif tool_name == TOOL_NAME:
|
||||
|
||||
# Check for tool confirmation if callback is provided
|
||||
tool_output = ""
|
||||
tool_executed = False
|
||||
if tool_name == TOOL_NAME and pre_tool_callback:
|
||||
script = tool_args.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "id": tool_id, "script": script})
|
||||
tool_output = _run_script(script, base_dir, qa_callback)
|
||||
else:
|
||||
tool_output = f"ERROR: unknown tool '{tool_name}'"
|
||||
res = pre_tool_callback(script, base_dir, qa_callback)
|
||||
if res is None:
|
||||
tool_output = "USER REJECTED: tool execution cancelled"
|
||||
else:
|
||||
tool_output = res
|
||||
tool_executed = True
|
||||
|
||||
if not tool_executed:
|
||||
events.emit("tool_execution", payload={"status": "started", "tool": tool_name, "args": tool_args, "round": round_idx})
|
||||
if tool_name in mcp_client.TOOL_NAMES:
|
||||
_append_comms("OUT", "tool_call", {"name": tool_name, "id": tool_id, "args": tool_args})
|
||||
tool_output = mcp_client.dispatch(tool_name, tool_args)
|
||||
elif tool_name == TOOL_NAME:
|
||||
script = tool_args.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {"name": TOOL_NAME, "id": tool_id, "script": script})
|
||||
tool_output = _run_script(script, base_dir, qa_callback)
|
||||
else:
|
||||
tool_output = f"ERROR: unknown tool '{tool_name}'"
|
||||
|
||||
if i == len(tool_calls_raw) - 1:
|
||||
if file_items:
|
||||
file_items, changed = _reread_file_items(file_items)
|
||||
|
||||
Reference in New Issue
Block a user