#!/usr/bin/env python3
"""
gonext probe agent (agentic mode for the gonext local worker).

Reads a JSON probe config on stdin and writes a single JSON object on stdout:

  in:  {"request": {"method","url"},
        "measurement": {"status","statusText","latencyMs","headers",
                        "bodySnippet","bodyBytes"} | null,
        "category": str, "error": str | null,
        "agentBaseURL","agentApiKey","agentModelId"}
  out: {"agentSummary": str, "error": str | null}

The worker performs the authoritative HTTP measurement (reliable TLS via Node
fetch) and passes it here; this script drives a smolagents agent on the selected
local model to produce the natural-language health assessment. The agent's
`send_request` tool returns the already-measured result, so there is exactly one
network call (the worker's) and the measured status stays the source of truth.

smolagents/rich writes its console UI to stdout, so we redirect stdout to stderr
during the agent run and only emit our JSON result on stdout.

See docs/plans/smolagents-local-worker-http-probe.md.
"""
import contextlib
import json
import sys


def describe(measurement, category, error):
    if not measurement or error:
        return f"The request did not get a response ({category}): {error or 'unknown error'}."
    return (
        f"HTTP {measurement.get('status')} {measurement.get('statusText', '')} "
        f"({category}) in {measurement.get('latencyMs')} ms. "
        f"Body preview: {str(measurement.get('bodySnippet', ''))[:400]}"
    )


def run_agent_summary(cfg):
    """Returns (summary, error). Never raises."""
    try:
        from smolagents import CodeAgent, OpenAIServerModel, tool
    except Exception as e:  # noqa: BLE001
        return "", f"smolagents not installed ({e})"

    request = cfg.get("request") or {}
    method = (request.get("method") or "GET").upper()
    url = request.get("url") or ""
    measurement = cfg.get("measurement")
    category = cfg.get("category") or ""
    error = cfg.get("error")
    measured_text = describe(measurement, category, error)

    @tool
    def send_request() -> str:
        """Send the configured HTTP request to the target endpoint and return its
        status code and a short body preview."""
        return measured_text

    try:
        model = OpenAIServerModel(
            model_id=cfg.get("agentModelId") or "",
            api_base=cfg.get("agentBaseURL") or "",
            api_key=cfg.get("agentApiKey") or "local",
        )
        agent = CodeAgent(tools=[send_request], model=model, max_steps=4)
        task = (
            f"Use send_request to call {method} {url}. Then report the HTTP status "
            "code, classify it (2xx success, 3xx redirect, 4xx client error, 5xx "
            "server error, or network failure), and give a one-sentence health "
            "assessment of the endpoint."
        )
        # smolagents/rich logs to stdout; keep stdout clean for our JSON result.
        with contextlib.redirect_stdout(sys.stderr):
            summary = str(agent.run(task)).strip()
        return summary, None
    except Exception as e:  # noqa: BLE001
        return "", f"agent run failed ({e})"


def main():
    try:
        cfg = json.load(sys.stdin)
    except Exception as e:  # noqa: BLE001
        json.dump({"agentSummary": "", "error": f"invalid input: {e}"}, sys.stdout)
        return
    summary, agent_error = run_agent_summary(cfg)
    json.dump({"agentSummary": summary, "error": agent_error}, sys.stdout)


if __name__ == "__main__":
    main()
