import asyncio
import os

MAX_OUTPUT = 100_000  # 100KB
DEFAULT_TIMEOUT = 30


async def handler(params: dict) -> dict:
    """Execute a shell command."""
    command = params["command"]
    directory = params.get("directory") or os.getcwd()
    timeout = params.get("timeout") or DEFAULT_TIMEOUT

    try:
        proc = await asyncio.create_subprocess_shell(
            command,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
            cwd=directory,
        )
        stdout_bytes, stderr_bytes = await asyncio.wait_for(
            proc.communicate(), timeout=timeout
        )
    except asyncio.TimeoutError:
        proc.kill()
        await proc.communicate()
        return {
            "stdout": "",
            "stderr": f"Command timed out after {timeout}s",
            "exit_code": -1,
        }

    stdout = stdout_bytes.decode("utf-8", errors="replace")
    stderr = stderr_bytes.decode("utf-8", errors="replace")

    if len(stdout) > MAX_OUTPUT:
        stdout = stdout[:MAX_OUTPUT] + "\n... (truncated)"
    if len(stderr) > MAX_OUTPUT:
        stderr = stderr[:MAX_OUTPUT] + "\n... (truncated)"

    return {
        "stdout": stdout,
        "stderr": stderr,
        "exit_code": proc.returncode,
    }
