{% if sdk_type == "codex_agent_sdk" %}
"""Codex SDK Hello World.

This agent uses OpenAI Agents `codex_tool` and forwards Codex thread events
to TerminalUse raw events.
"""

from __future__ import annotations

import os
from typing import Any

from agents import Agent, ModelSettings, Runner
from agents.extensions.experimental.codex import (
    CodexToolStreamEvent,
    ThreadOptions,
    codex_tool,
)
from agents.extensions.experimental.codex.events import (
    ThreadError,
    ThreadEvent,
    ThreadStartedEvent,
    TurnFailedEvent,
)

from terminaluse.lib import (
    AgentServer,
    TaskContext,
    make_logger,
)
from terminaluse.types import Event, TextPart

logger = make_logger(__name__)

# Create an agent server
server = AgentServer()


@server.on_create
async def handle_create(ctx: TaskContext, params: dict[str, Any]):
    """Handle task creation."""
    # Persist Codex thread id so subsequent turns can resume.
    await ctx.state.create(
        state={
            "thread_id": None,
        },
    )


@server.on_event
async def handle_event(ctx: TaskContext, event: Event):
    """Handle incoming user messages and route them to Codex."""
    os.environ.setdefault("CODEX_HOME", "/root/.codex")

    state = await ctx.state.get()
    thread_id = state.get("thread_id") if state else None
    if not isinstance(thread_id, str):
        thread_id = None
    resolved_thread_id = thread_id

    async def _on_codex_stream(payload: CodexToolStreamEvent) -> None:
        nonlocal resolved_thread_id
        thread_event: ThreadEvent = payload.event
        await ctx.messages.send(thread_event)
        if isinstance(thread_event, ThreadStartedEvent):
            resolved_thread_id = thread_event.thread_id

    if not isinstance(event.content, TextPart):
        await ctx.messages.send(
            TurnFailedEvent(
                error=ThreadError(
                    message="Unsupported message type. Only text messages are supported."
                ),
            )
        )
        return

    user_message = event.content.text

    try:
        codex_agent = Agent(
            name="Codex Runtime Agent",
            instructions=(
                "For every user request, call the codex tool exactly once using the user request "
                "as a text input. Keep your final response concise."
            ),
            model_settings=ModelSettings(tool_choice="required"),
            tools=[
                codex_tool(
                    thread_id=thread_id,
                    default_thread_options=ThreadOptions(
                        working_directory="/workspace",
                        skip_git_repo_check=True,
                        sandbox_mode="danger-full-access",
                        approval_policy="never",
                    ),
                    on_stream=_on_codex_stream,
                    failure_error_function=None,
                )
            ],
        )

        await Runner.run(codex_agent, user_message)
    except Exception as e:
        await ctx.messages.send(
            TurnFailedEvent(
                error=ThreadError(message=str(e)),
            )
        )
    finally:
        if isinstance(resolved_thread_id, str) and resolved_thread_id and resolved_thread_id != thread_id:
            await ctx.state.update({"thread_id": resolved_thread_id})


@server.on_cancel
async def handle_cancel(ctx: TaskContext):
    """Handle task cancellation."""
    logger.info(f"Task cancelled: {ctx.task.id}")
{% else %}
"""Claude Agent SDK Hello World.

This agent uses the Claude Agent SDK to have intelligent conversations.
It can read/write files, run commands, and maintains context across turns.
"""

from typing import Any

from claude_agent_sdk import ClaudeAgentOptions, query
from claude_agent_sdk.types import ResultMessage

from terminaluse.lib import (
    AgentServer,
    TaskContext,
    make_logger,
)
from terminaluse.types import Event, TextPart

logger = make_logger(__name__)

# Create an agent server
server = AgentServer()


@server.on_create
async def handle_create(ctx: TaskContext, params: dict[str, Any]):
    """Handle task creation.
    """
    # Initialize state - session_id will be set after first query
    await ctx.state.create(
        state={
            "session_id": None,
        },
    )


@server.on_event
async def handle_event(ctx: TaskContext, event: Event):
    """Handle incoming messages from users.

    Routes messages to Claude and streams responses back.
    """
    try:
        # Parse user message
        if not isinstance(event.content, TextPart):
            raise ValueError("Unsupported message type. Only text messages are supported.")
        user_message = event.content.text

        # Get state for to get the session ID
        state = await ctx.state.get()
        session_id = state.get("session_id") if state else None

        # Configure Claude Agent SDK
        options = ClaudeAgentOptions(
            include_partial_messages=True, # enable streaming
            permission_mode="bypassPermissions",
            cwd="/workspace",
            allowed_tools=["Skill", "Read", "Write", "Bash", "Edit", "Grep", "Glob"],
            resume=session_id,  # Resume previous session if exists
        )

        # Query Claude and stream responses
        async for message in query(prompt=user_message, options=options):
            await ctx.messages.send(message)

            # Save session ID for continuity
            if isinstance(message, ResultMessage):
                await ctx.state.update(
                    {"session_id": message.session_id}
                )

    except Exception as e:
        error_msg = str(e)
        await ctx.messages.send(f"Sorry, I encountered an error: {error_msg}")


@server.on_cancel
async def handle_cancel(ctx: TaskContext):
    """Handle task cancellation.

    Clean up any resources or state when a task is cancelled.
    """
    logger.info(f"Task cancelled: {ctx.task.id}")
{% endif %}
