"""Run: pip install --upgrade openai; python order_agent.py
Set OPENAI_API_KEY first. This uses API credits and a fictional read-only order.
"""
import json
import sys


def lookup_order(arguments, user_id):
    if not isinstance(arguments, dict) or set(arguments) != {"order_id"}:
        raise ValueError("Expected only order_id")
    if user_id != "demo-user" or arguments["order_id"] != "ORDER-100":
        raise ValueError("Order not found or not accessible")
    return {"order_id": "ORDER-100", "status": "shipped"}


def run_order(client, user_id="demo-user", progress=print):
    session_id = None
    parts, results = {}, {}
    try:
        with client.beta.agents.sessions.create(
            agent={
                "model": "gpt-6-astra",
                "instructions": "Use lookup_order for order facts. Never invent a status.",
                "tools": [{
                    "type": "function", "name": "lookup_order",
                    "description": "Read an order owned by the current user.",
                    "parameters": {"type": "object", "properties": {
                        "order_id": {"type": "string"}},
                        "required": ["order_id"], "additionalProperties": False},
                }],
            },
            environment={"type": "none"},
            input="Use lookup_order to find the status of ORDER-100.", stream=True,
        ) as events:
            for model_event in events:
                event = model_event.to_dict()
                session_id = event.get("session_id") or event.get("session", {}).get("id") or session_id
                kind = event["type"]
                progress(json.dumps({"type": kind, "session_id": session_id}))
                if kind == "agent.session.requires_action":
                    if not session_id:
                        raise RuntimeError("Missing session ID")
                    session = client.beta.agents.sessions.retrieve(session_id)
                    for model_action in session.required_actions:
                        action = model_action.to_dict()
                        if action["type"] != "function_call":
                            raise RuntimeError("Unexpected environment action")
                        key = (action["turn_id"], action["call_id"])
                        if key not in results:
                            try:
                                if action["name"] != "lookup_order":
                                    raise ValueError("Unknown tool")
                                value = lookup_order(action["arguments"], user_id)
                                results[key] = {"success": True, "output": json.dumps(value)}
                            except ValueError as error:
                                results[key] = {"success": False, "error": str(error)}
                        client.beta.agents.sessions.events.create(session_id, events=[{
                            "type": "agent.session.input.tool_result", "turn_id": key[0],
                            "call_id": key[1], **results[key],
                        }])
                if kind in ("agent.session.turn.output_text.delta", "agent.session.turn.output_text.done") and not event.get("subagent_id"):
                    key = (event["item_id"], event["content_index"])
                    parts[key] = event["text"] if kind.endswith(".done") else parts.get(key, "") + event["delta"]
                if kind in ("error", "agent.session.failed", "agent.session.environment.failed"):
                    raise RuntimeError("Session or environment failure")
                if not event.get("turn", {}).get("subagent_id"):
                    if kind in ("agent.session.turn.failed", "agent.session.turn.cancelled"):
                        raise RuntimeError("Root turn did not complete")
                    if kind == "agent.session.turn.completed":
                        return {"session_id": session_id, "text": "\n".join(parts.values()),
                                "tool_results": list(results.values())}
        raise RuntimeError("Stream ended before a root outcome")
    except Exception as error:
        # Preserve correlation without copying raw provider payloads or credentials.
        raise RuntimeError(f"Run interrupted; session={session_id}. Inspect saved state before retrying.") from error


if __name__ == "__main__":
    from openai import OpenAI
    try:
        with OpenAI(max_retries=0, timeout=30.0) as api:
            print(json.dumps(run_order(api), indent=2))
    except Exception as error:
        print(str(error), file=sys.stderr)
        sys.exit(1)
