feat(mma): Implement run_tier4_analysis in ai_client.py
This commit is contained in:
37
ai_client.py
37
ai_client.py
@@ -1764,6 +1764,43 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
|||||||
raise _classify_deepseek_error(e) from e
|
raise _classify_deepseek_error(e) from e
|
||||||
|
|
||||||
|
|
||||||
|
def run_tier4_analysis(stderr: str) -> str:
|
||||||
|
"""
|
||||||
|
Stateless Tier 4 QA analysis of an error message.
|
||||||
|
Uses gemini-2.5-flash-lite to summarize the error and suggest a fix.
|
||||||
|
"""
|
||||||
|
if not stderr or not stderr.strip():
|
||||||
|
return ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
_ensure_gemini_client()
|
||||||
|
prompt = (
|
||||||
|
f"You are a Tier 4 QA Agent specializing in error analysis.\n"
|
||||||
|
f"Analyze the following stderr output from a PowerShell command:\n\n"
|
||||||
|
f"```\n{stderr}\n```\n\n"
|
||||||
|
f"Provide a concise summary of the failure and suggest a fix in approximately 20 words."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use flash-lite for cost-effective stateless analysis
|
||||||
|
model_name = "gemini-2.5-flash-lite"
|
||||||
|
|
||||||
|
# We don't use the chat session here to keep it stateless
|
||||||
|
resp = _gemini_client.models.generate_content(
|
||||||
|
model=model_name,
|
||||||
|
contents=prompt,
|
||||||
|
config=types.GenerateContentConfig(
|
||||||
|
temperature=0.0,
|
||||||
|
max_output_tokens=150,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
analysis = resp.text.strip()
|
||||||
|
return analysis
|
||||||
|
except Exception as e:
|
||||||
|
# We don't want to crash the main loop if QA analysis fails
|
||||||
|
return f"[QA ANALYSIS FAILED] {e}"
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------ unified send
|
# ------------------------------------------------------------------ unified send
|
||||||
|
|
||||||
def send(
|
def send(
|
||||||
|
|||||||
@@ -100,3 +100,29 @@ def test_run_powershell_optional_qa_callback():
|
|||||||
|
|
||||||
assert "STDERR:\nerror" in output
|
assert "STDERR:\nerror" in output
|
||||||
assert "EXIT CODE: 1" in output
|
assert "EXIT CODE: 1" in output
|
||||||
|
|
||||||
|
def test_end_to_end_tier4_integration():
|
||||||
|
"""
|
||||||
|
Verifies that shell_runner.run_powershell correctly uses ai_client.run_tier4_analysis.
|
||||||
|
"""
|
||||||
|
import ai_client
|
||||||
|
|
||||||
|
script = "Invoke-Item non_existent_file"
|
||||||
|
base_dir = "."
|
||||||
|
stderr_content = "Invoke-Item : Cannot find path 'C:\\non_existent_file' because it does not exist."
|
||||||
|
|
||||||
|
mock_result = MagicMock()
|
||||||
|
mock_result.stdout = ""
|
||||||
|
mock_result.stderr = stderr_content
|
||||||
|
mock_result.returncode = 1
|
||||||
|
|
||||||
|
expected_analysis = "Path does not exist. Verify the file path and ensure the file is present before invoking."
|
||||||
|
|
||||||
|
with patch("subprocess.run", return_value=mock_result), \
|
||||||
|
patch("shutil.which", return_value="powershell.exe"), \
|
||||||
|
patch("ai_client.run_tier4_analysis", return_value=expected_analysis) as mock_analysis:
|
||||||
|
|
||||||
|
output = run_powershell(script, base_dir, qa_callback=ai_client.run_tier4_analysis)
|
||||||
|
|
||||||
|
mock_analysis.assert_called_once_with(stderr_content)
|
||||||
|
assert f"QA ANALYSIS:\n{expected_analysis}" in output
|
||||||
|
|||||||
Reference in New Issue
Block a user